Implementing proper package uninstall process with features being disabled and uninstalled, then the package being removed.

This commit is contained in:
Lombiq
2015-01-27 18:33:09 +01:00
committed by Zoltán Lehóczky
parent aa94c1d5f4
commit 10c0baabf4
3 changed files with 121 additions and 2 deletions

View File

@@ -110,6 +110,7 @@
<Compile Include="Services\PackageInstaller.cs" />
<Compile Include="Services\PackageManager.cs" />
<Compile Include="Models\PackagingEntry.cs" />
<Compile Include="Services\PackageUninstallHandler.cs" />
<Compile Include="Services\PackageUpdateManager.cs" />
<Compile Include="Services\PackagingSourceManager.cs" />
<Compile Include="ViewModels\PackagingAddSourceViewModel.cs" />

View File

@@ -5,6 +5,8 @@ using NuGet;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Folders;
using Orchard.Environment.Extensions.Models;
using Orchard.Environment.Features;
using Orchard.Environment.State;
using Orchard.Localization;
using Orchard.Packaging.Models;
@@ -14,14 +16,23 @@ namespace Orchard.Packaging.Services {
private readonly IExtensionManager _extensionManager;
private readonly IPackageBuilder _packageBuilder;
private readonly IPackageInstaller _packageInstaller;
private readonly IShellStateManager _shellStateManager;
private readonly IFeatureManager _featureManager;
private readonly IPackageUninstallHandler _packageUninstallHandler;
public PackageManager(
IExtensionManager extensionManager,
IPackageBuilder packageBuilder,
IPackageInstaller packageInstaller) {
IPackageInstaller packageInstaller,
IShellStateManager shellStateManager,
IFeatureManager featureManager,
IPackageUninstallHandler packageUninstallHandler) {
_extensionManager = extensionManager;
_packageBuilder = packageBuilder;
_packageInstaller = packageInstaller;
_shellStateManager = shellStateManager;
_featureManager = featureManager;
_packageUninstallHandler = packageUninstallHandler;
T = NullLocalizer.Instance;
}
@@ -69,7 +80,30 @@ namespace Orchard.Packaging.Services {
}
public void Uninstall(string packageId, string applicationPath) {
_packageInstaller.Uninstall(packageId, applicationPath);
var extensionToUninstall = _extensionManager.AvailableExtensions()
.FirstOrDefault(extension => PackageBuilder.BuildPackageId(extension.Id, extension.ExtensionType) == packageId);
if (extensionToUninstall == null) {
throw new OrchardException(T("There is no extension that has the package ID \"{0}\".", packageId));
}
var featureIdsToUninstall = extensionToUninstall.Features.Select(feature => feature.Id);
var shellState = _shellStateManager.GetShellState();
var featureStates = shellState.Features.Where(featureState => featureIdsToUninstall.Contains(featureState.Name));
// This means that no feature from this extension wasn enabled yet, can be uninstalled directly.
if (!featureStates.Any()) {
_packageUninstallHandler.QueuePackageUninstall(packageId);
}
else {
_featureManager.DisableFeatures(extensionToUninstall.Features.Select(feature => feature.Id), true);
// Installed state can't be deduced from the shell state changes like for enabled state, so have to
// set that explicitly.
foreach (var featureState in featureStates) {
_shellStateManager.UpdateInstalledState(featureState, Environment.State.Models.ShellFeatureState.State.Falling);
}
}
}
#endregion

View File

@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Orchard.Environment;
using Orchard.Environment.Configuration;
using Orchard.Environment.Descriptor;
using Orchard.Environment.Extensions.Models;
using Orchard.Environment.State;
using Orchard.Events;
namespace Orchard.Packaging.Services {
public interface IPackageUninstallHandler : IEventHandler {
/// <summary>
/// Queues a package to be uninstalled after the request is processed.
/// </summary>
/// <param name="packageId">The textual ID of the package.</param>
void QueuePackageUninstall(string packageId);
/// <summary>
/// Uninstalls the given package from the system.
/// </summary>
/// <param name="packageId">The textual ID of the package.</param>
void UninstallPackage(string packageId);
}
public class PackageUninstallHandler : IFeatureEventHandler, IPackageUninstallHandler {
private readonly ShellSettings _shellSettings;
private readonly IShellDescriptorManager _shellDescriptorManager;
private readonly IProcessingEngine _processingEngine;
private readonly IHostEnvironment _hostEnvironment;
private readonly IPackageInstaller _packageInstaller;
public PackageUninstallHandler(
ShellSettings shellSettings,
IShellDescriptorManager shellDescriptorManager,
IProcessingEngine processingEngine,
IHostEnvironment hostEnvironment,
IPackageInstaller packageInstaller) {
_shellSettings = shellSettings;
_shellDescriptorManager = shellDescriptorManager;
_processingEngine = processingEngine;
_hostEnvironment = hostEnvironment;
_packageInstaller = packageInstaller;
}
public void Installing(Feature feature) {
}
public void Installed(Feature feature) {
}
public void Enabling(Feature feature) {
}
public void Enabled(Feature feature) {
}
public void Disabling(Feature feature) {
}
public void Disabled(Feature feature) {
}
public void Uninstalling(Feature feature) {
}
public void Uninstalled(Feature feature) {
QueuePackageUninstall(PackageBuilder.BuildPackageId(feature.Descriptor.Extension.Id, feature.Descriptor.Extension.ExtensionType));
}
public void QueuePackageUninstall(string packageId) {
_processingEngine.AddTask(
_shellSettings,
_shellDescriptorManager.GetShellDescriptor(),
"IPackageUninstallHandler.UninstallPackage",
new Dictionary<string, object> { { "packageId", packageId } });
}
public void UninstallPackage(string packageId) {
_packageInstaller.Uninstall(packageId, _hostEnvironment.MapPath("~/"));
}
}
}