diff --git a/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs b/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs index 7ac2b2939..eafe8626f 100644 --- a/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs +++ b/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs @@ -59,6 +59,10 @@ namespace Orchard.Tests.Environment { public void InstallExtension(string extensionType, HttpPostedFileBase extensionBundle) { throw new NotImplementedException(); } + + public void UninstallExtension(string extensionType, string extensionName) { + throw new NotImplementedException(); + } } [Test] diff --git a/src/Orchard.Tests/Mvc/Routes/StandardExtensionRouteProviderTests.cs b/src/Orchard.Tests/Mvc/Routes/StandardExtensionRouteProviderTests.cs index 06e9d0e62..0a9083bcf 100644 --- a/src/Orchard.Tests/Mvc/Routes/StandardExtensionRouteProviderTests.cs +++ b/src/Orchard.Tests/Mvc/Routes/StandardExtensionRouteProviderTests.cs @@ -57,6 +57,10 @@ namespace Orchard.Tests.Mvc.Routes { public void InstallExtension(string extensionType, HttpPostedFileBase extensionBundle) { throw new NotImplementedException(); } + + public void UninstallExtension(string extensionType, string extensionName) { + throw new NotImplementedException(); + } } } } diff --git a/src/Orchard.Web/Core/Themes/Controllers/AdminController.cs b/src/Orchard.Web/Core/Themes/Controllers/AdminController.cs index a3ad751ca..ae492fd0d 100644 --- a/src/Orchard.Web/Core/Themes/Controllers/AdminController.cs +++ b/src/Orchard.Web/Core/Themes/Controllers/AdminController.cs @@ -67,7 +67,20 @@ namespace Orchard.Core.Themes.Controllers { return RedirectToAction("Index"); } catch (Exception exception) { - _notifier.Error("Installing theme failed: " + exception.Message); + _notifier.Error(T("Installing theme failed: " + exception.Message)); + return RedirectToAction("Index"); + } + } + + public ActionResult Uninstall(string themeName) { + try { + if (!_authorizer.Authorize(Permissions.InstallUninstallTheme, T("Couldn't uninstall theme"))) + return new HttpUnauthorizedResult(); + _themeService.UninstallTheme(themeName); + return RedirectToAction("Index"); + } + catch (Exception exception) { + _notifier.Error(T("Uninstalling theme failed: " + exception.Message)); return RedirectToAction("Index"); } } diff --git a/src/Orchard.Web/Core/Themes/Services/ThemeService.cs b/src/Orchard.Web/Core/Themes/Services/ThemeService.cs index ee4285b03..469774a40 100644 --- a/src/Orchard.Web/Core/Themes/Services/ThemeService.cs +++ b/src/Orchard.Web/Core/Themes/Services/ThemeService.cs @@ -76,6 +76,10 @@ namespace Orchard.Core.Themes.Services { _extensionManager.InstallExtension("Theme", file); } + public void UninstallTheme(string themeName) { + _extensionManager.UninstallExtension("Theme", themeName); + } + #endregion } } diff --git a/src/Orchard.Web/Core/Themes/Views/Admin/Index.aspx b/src/Orchard.Web/Core/Themes/Views/Admin/Index.aspx index 655dfdf40..a3edbe965 100644 --- a/src/Orchard.Web/Core/Themes/Views/Admin/Index.aspx +++ b/src/Orchard.Web/Core/Themes/Views/Admin/Index.aspx @@ -27,7 +27,7 @@ <%= theme.Version %>
<%= theme.Description %>
<%= theme.HomePage %>
- <%=Html.ActionLink("Activate", "Activate", new {themeName = theme.ThemeName}) %> + <%=Html.ActionLink("Activate", "Activate", new {themeName = theme.ThemeName}) %> | <%=Html.ActionLink("Uninstall", "Uninstall", new {themeName = theme.ThemeName}) %>

<% } diff --git a/src/Orchard/Extensions/ExtensionManager.cs b/src/Orchard/Extensions/ExtensionManager.cs index 73fd19667..2af5a799d 100644 --- a/src/Orchard/Extensions/ExtensionManager.cs +++ b/src/Orchard/Extensions/ExtensionManager.cs @@ -5,24 +5,22 @@ using System.Linq; using ICSharpCode.SharpZipLib.Zip; using Orchard.Extensions.Helpers; using Orchard.Extensions.Loaders; +using Orchard.Localization; using Yaml.Grammar; using System.Web; namespace Orchard.Extensions { - public interface IExtensionManager { - IEnumerable AvailableExtensions(); - IEnumerable ActiveExtensions(); - void InstallExtension(string extensionType, HttpPostedFileBase extensionBundle); - } - public class ExtensionManager : IExtensionManager { private readonly IEnumerable _folders; private readonly IEnumerable _loaders; private IEnumerable _activeExtensions; + public Localizer T { get; set; } + public ExtensionManager(IEnumerable folders, IEnumerable loaders) { _folders = folders; _loaders = loaders.OrderBy(x => x.Order); + T = NullLocalizer.Instance; } @@ -73,7 +71,7 @@ namespace Orchard.Extensions { public void InstallExtension(string extensionType, HttpPostedFileBase extensionBundle) { if (String.IsNullOrEmpty(extensionType)) { - throw new ArgumentException("extensionType"); + throw new ArgumentException(T("extensionType was null or empty").ToString()); } string targetFolder; if (String.Equals(extensionType, "Theme", StringComparison.OrdinalIgnoreCase)) { @@ -83,7 +81,7 @@ namespace Orchard.Extensions { targetFolder = PathHelpers.GetPhysicalPath("~/Packages"); } else { - throw new ArgumentException("extensionType"); + throw new ArgumentException(T("extensionType was not recognized").ToString()); } int postedFileLength = extensionBundle.ContentLength; Stream postedFileStream = extensionBundle.InputStream; @@ -109,6 +107,27 @@ namespace Orchard.Extensions { } } + public void UninstallExtension(string extensionType, string extensionName) { + if (String.IsNullOrEmpty(extensionType)) { + throw new ArgumentException(T("extensionType was null or empty").ToString()); + } + string targetFolder; + if (String.Equals(extensionType, "Theme", StringComparison.OrdinalIgnoreCase)) { + targetFolder = PathHelpers.GetPhysicalPath("~/Themes"); + } + else if (String.Equals(extensionType, "Package", StringComparison.OrdinalIgnoreCase)) { + targetFolder = PathHelpers.GetPhysicalPath("~/Packages"); + } + else { + throw new ArgumentException(T("extensionType was not recognized").ToString()); + } + targetFolder = Path.Combine(targetFolder, extensionName); + if (!Directory.Exists(targetFolder)) { + throw new ArgumentException(T("extension was not found").ToString()); + } + Directory.Delete(targetFolder, true); + } + private IEnumerable BuildActiveExtensions() { //TODO: this component needs access to some "current settings" to know which are active foreach (var descriptor in AvailableExtensions()) { diff --git a/src/Orchard/Extensions/IExtensionManager.cs b/src/Orchard/Extensions/IExtensionManager.cs new file mode 100644 index 000000000..fb6199f2d --- /dev/null +++ b/src/Orchard/Extensions/IExtensionManager.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Web; + +namespace Orchard.Extensions { + public interface IExtensionManager { + IEnumerable AvailableExtensions(); + IEnumerable ActiveExtensions(); + void InstallExtension(string extensionType, HttpPostedFileBase extensionBundle); + void UninstallExtension(string extensionType, string extensionName); + } +} \ No newline at end of file diff --git a/src/Orchard/Orchard.csproj b/src/Orchard/Orchard.csproj index 91a06d5de..a96e86f1e 100644 --- a/src/Orchard/Orchard.csproj +++ b/src/Orchard/Orchard.csproj @@ -126,6 +126,7 @@ + diff --git a/src/Orchard/Themes/IThemeService.cs b/src/Orchard/Themes/IThemeService.cs index 5fd54f5bb..2bfca96be 100644 --- a/src/Orchard/Themes/IThemeService.cs +++ b/src/Orchard/Themes/IThemeService.cs @@ -8,5 +8,6 @@ namespace Orchard.Themes { IEnumerable GetInstalledThemes(); void SetCurrentTheme(string themeName); void InstallTheme(HttpPostedFileBase file); + void UninstallTheme(string themeName); } }