mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Merge branch 'feature/module-uninstall' into 1.x
This commit is contained in:
@@ -92,9 +92,13 @@ namespace Orchard.Modules.Controllers {
|
||||
modules = modules.Skip((pager.Page - 1) * pager.PageSize).Take(pager.PageSize);
|
||||
}
|
||||
|
||||
// This way we can more or less reliably handle this implicit dependency.
|
||||
var installModules = _featureManager.GetEnabledFeatures().FirstOrDefault(f => f.Id == "PackagingServices") != null;
|
||||
|
||||
modules = modules.ToList();
|
||||
foreach (ModuleEntry moduleEntry in modules) {
|
||||
moduleEntry.IsRecentlyInstalled = _moduleService.IsRecentlyInstalled(moduleEntry.Descriptor);
|
||||
moduleEntry.CanUninstall = installModules;
|
||||
|
||||
if (_extensionDisplayEventHandler != null) {
|
||||
foreach (string notification in _extensionDisplayEventHandler.Displaying(moduleEntry.Descriptor, ControllerContext.RequestContext)) {
|
||||
@@ -103,9 +107,10 @@ namespace Orchard.Modules.Controllers {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return View(new ModulesIndexViewModel {
|
||||
Modules = modules,
|
||||
InstallModules = _featureManager.GetEnabledFeatures().FirstOrDefault(f => f.Id == "PackagingServices") != null,
|
||||
InstallModules = installModules,
|
||||
Options = options,
|
||||
Pager = Shape.Pager(pager).TotalItemCount(totalItemCount)
|
||||
});
|
||||
|
||||
@@ -32,5 +32,10 @@ namespace Orchard.Modules.Models {
|
||||
/// List of module notifications.
|
||||
/// </summary>
|
||||
public List<string> Notifications { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the module can be uninstalled by the user.
|
||||
/// </summary>
|
||||
public bool CanUninstall { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -17,16 +17,17 @@
|
||||
</fieldset>
|
||||
|
||||
if (Model.InstallModules) {
|
||||
<span>@Html.ActionLink(T("Install a module from your computer").ToString(), "AddModule", "PackagingServices", new { area = "Orchard.Packaging", returnUrl = HttpContext.Current.Request.RawUrl }, null)</span>
|
||||
}
|
||||
<span>@Html.ActionLink(T("Install a module from your computer").ToString(), "AddModule", "PackagingServices", new { area = "Orchard.Packaging", returnUrl = HttpContext.Current.Request.RawUrl }, null)</span>
|
||||
}
|
||||
|
||||
if (Model.Modules.Any()) {
|
||||
<ul class="contentItems">
|
||||
@foreach (ModuleEntry module in Model.Modules.OrderBy(m => m.Descriptor.Name)) {
|
||||
<li>@Display.ModuleEntry(ContentPart: module)</li>
|
||||
<li>@Display.ModuleEntry(Module: module)</li>
|
||||
}
|
||||
</ul>
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
<p>@T("No modules available").ToString()</p>
|
||||
}
|
||||
|
||||
|
||||
@@ -6,34 +6,34 @@
|
||||
}
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
if (Model.Modules.Any()) {
|
||||
<ul class="contentItems">
|
||||
@foreach (var moduleEntry in Model.Modules.OrderBy(m => m.Module.Descriptor.Name)) {
|
||||
var module = moduleEntry.Module;
|
||||
var descriptor = module.Descriptor;
|
||||
<ul class="contentItems">
|
||||
@foreach (var moduleEntry in Model.Modules.OrderBy(m => m.Module.Descriptor.Name)) {
|
||||
var module = moduleEntry.Module;
|
||||
var descriptor = module.Descriptor;
|
||||
|
||||
<li>
|
||||
<div class="summary">
|
||||
<div class="properties">
|
||||
<h2>@descriptor.Name<span> - @T("Version: {0}", !string.IsNullOrEmpty(descriptor.Version) ? descriptor.Version : T("1.0").ToString())</span></h2>
|
||||
<li>
|
||||
<div class="summary">
|
||||
<div class="properties">
|
||||
<h2>@descriptor.Name<span> - @T("Version: {0}", !string.IsNullOrEmpty(descriptor.Version) ? descriptor.Version : T("1.0").ToString())</span></h2>
|
||||
|
||||
@*@if (!string.IsNullOrEmpty(descriptor.Description)) {
|
||||
<p>@descriptor.Description</p>
|
||||
}*@
|
||||
|
||||
@foreach (var recipe in moduleEntry.Recipes) {
|
||||
<br/>
|
||||
<div>
|
||||
<h4>@recipe.Name.CamelFriendly() - @Html.ActionLink(T("Execute").Text, "Recipes", "Admin", new {area = "Orchard.Modules", moduleId = descriptor.Id, name = recipe.Name}, new {itemprop = "UnsafeUrl"})</h4>
|
||||
<p>@(!string.IsNullOrEmpty(recipe.Description) ? recipe.Description : T("No description").ToString())</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
else {
|
||||
<p>@T("No modules available").ToString()</p>
|
||||
}
|
||||
@*@if (!string.IsNullOrEmpty(descriptor.Description)) {
|
||||
<p>@descriptor.Description</p>
|
||||
}*@
|
||||
|
||||
@foreach (var recipe in moduleEntry.Recipes) {
|
||||
<br />
|
||||
<div>
|
||||
<h4>@recipe.Name.CamelFriendly() - @Html.ActionLink(T("Execute").Text, "Recipes", "Admin", new { area = "Orchard.Modules", moduleId = descriptor.Id, name = recipe.Name }, new { itemprop = "UnsafeUrl" })</h4>
|
||||
<p>@(!string.IsNullOrEmpty(recipe.Description) ? recipe.Description : T("No description").ToString())</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
else {
|
||||
<p>@T("No modules available").ToString()</p>
|
||||
}
|
||||
}
|
||||
@@ -2,30 +2,46 @@
|
||||
@using Orchard.Mvc.Html;
|
||||
@using Orchard.Modules.ViewModels;
|
||||
@using Orchard.Environment.Extensions.Models;
|
||||
@using Orchard.Utility.Extensions;
|
||||
|
||||
@{ string moduleClasses = Model.ContentPart.IsRecentlyInstalled ? "recentlyInstalledModule" : string.Empty; }
|
||||
@{
|
||||
Script.Require("ShapesBase").AtFoot();
|
||||
|
||||
Orchard.Modules.Models.ModuleEntry module = Model.Module;
|
||||
var moduleClasses = module.IsRecentlyInstalled ? "class=\"recentlyInstalledModule\"" : String.Empty;
|
||||
}
|
||||
|
||||
<div class="summary">
|
||||
@if (Model.ContentPart.Notifications != null && Model.ContentPart.Notifications.Count > 0) {
|
||||
<div class="notifications">
|
||||
@foreach (string notification in Model.ContentPart.Notifications) {
|
||||
@if (module.Notifications != null && module.Notifications.Count > 0) {
|
||||
<div class="notifications">
|
||||
@foreach (var notification in module.Notifications) {
|
||||
<h5>@Html.Raw(notification)</h5>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<div class="properties">
|
||||
<h2@{ if(!string.IsNullOrEmpty(moduleClasses)) {<text> class="@moduleClasses"</text>}}>@Model.ContentPart.Descriptor.Name<span> - @T("Version: {0}", !string.IsNullOrEmpty(Model.ContentPart.Descriptor.Version) ? Model.ContentPart.Descriptor.Version : T("1.0").ToString())</span></h2>
|
||||
<h2 @Html.Raw(moduleClasses)>
|
||||
@module.Descriptor.Name<span> - @T("Version: {0}", !String.IsNullOrEmpty(module.Descriptor.Version) ? module.Descriptor.Version : T("1.0").ToString())</span>
|
||||
</h2>
|
||||
|
||||
@if (!string.IsNullOrEmpty(Model.ContentPart.Descriptor.Description)) {
|
||||
<p>@Model.ContentPart.Descriptor.Description</p>
|
||||
@Html.ActionLink(
|
||||
T("Uninstall").Text,
|
||||
"UninstallModule",
|
||||
"PackagingServices",
|
||||
new { ModuleId = module.Descriptor.Id, ReturnUrl = Request.ToUrlString(), Area = "Orchard.Packaging" },
|
||||
new { itemprop = "RemoveUrl UnsafeUrl" })
|
||||
|
||||
@if (!String.IsNullOrEmpty(module.Descriptor.Description)) {
|
||||
<p>@module.Descriptor.Description</p>
|
||||
}
|
||||
|
||||
<ul class="pageStatus" style="color:#666; margin:.6em 0 0 0;">
|
||||
@{ IEnumerable<FeatureDescriptor> features = Model.ContentPart.Descriptor.Features; }
|
||||
<li>@T("Features: {0}", MvcHtmlString.Create(string.Join(", ", features.Select(f => Html.Link(string.IsNullOrEmpty(f.Name) ? f.Id : f.Name, string.Format("{0}#{1}", Url.Action("features", new { area = "Orchard.Modules" }), f.Id.AsFeatureId(n => T(n)))).ToString()).OrderBy(s => s).ToArray())))</li>
|
||||
<li> | @T("Author: {0}", !string.IsNullOrEmpty(Model.ContentPart.Descriptor.Author) ? Model.ContentPart.Descriptor.Author : T("Unknown").ToString())</li>
|
||||
<li> | @T("Website: ")
|
||||
@if (!string.IsNullOrEmpty(Model.ContentPart.Descriptor.WebSite)) { <a href="@Model.ContentPart.Descriptor.WebSite">@Model.ContentPart.Descriptor.WebSite</a> }
|
||||
@{ var features = module.Descriptor.Features; }
|
||||
<li>@T("Features: {0}", MvcHtmlString.Create(String.Join(", ", features.Select(f => Html.Link(String.IsNullOrEmpty(f.Name) ? f.Id : f.Name, String.Format("{0}#{1}", Url.Action("features", new { area = "Orchard.Modules" }), f.Id.AsFeatureId(n => T(n)))).ToString()).OrderBy(s => s).ToArray())))</li>
|
||||
<li> | @T("Author: {0}", !String.IsNullOrEmpty(module.Descriptor.Author) ? module.Descriptor.Author : T("Unknown").ToString())</li>
|
||||
<li>
|
||||
| @T("Website: ")
|
||||
@if (!String.IsNullOrEmpty(module.Descriptor.WebSite)) { <a href="@module.Descriptor.WebSite">@module.Descriptor.WebSite</a> }
|
||||
else { @T("Unknown").ToString() }
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -2,10 +2,12 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Web.Hosting;
|
||||
using System.Web.Mvc;
|
||||
using System.Xml.Linq;
|
||||
using NuGet;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.FileSystems.AppData;
|
||||
@@ -33,6 +35,7 @@ namespace Orchard.Packaging.Controllers {
|
||||
private readonly IPackagingSourceManager _packagingSourceManager;
|
||||
private readonly IAppDataFolderRoot _appDataFolderRoot;
|
||||
private readonly IModuleService _moduleService;
|
||||
private readonly IHostEnvironment _hostEnvironment;
|
||||
private readonly IRecipeHarvester _recipeHarvester;
|
||||
private readonly IRecipeManager _recipeManager;
|
||||
|
||||
@@ -42,8 +45,9 @@ namespace Orchard.Packaging.Controllers {
|
||||
IPackagingSourceManager packagingSourceManager,
|
||||
IAppDataFolderRoot appDataFolderRoot,
|
||||
IOrchardServices services,
|
||||
IModuleService moduleService)
|
||||
: this(shellSettings, packageManager, packagingSourceManager, appDataFolderRoot, services, moduleService, null, null) {
|
||||
IModuleService moduleService,
|
||||
IHostEnvironment hostEnvironment)
|
||||
: this(shellSettings, packageManager, packagingSourceManager, appDataFolderRoot, services, moduleService, hostEnvironment, null, null) {
|
||||
}
|
||||
|
||||
public PackagingServicesController(
|
||||
@@ -53,6 +57,7 @@ namespace Orchard.Packaging.Controllers {
|
||||
IAppDataFolderRoot appDataFolderRoot,
|
||||
IOrchardServices services,
|
||||
IModuleService moduleService,
|
||||
IHostEnvironment hostEnvironment,
|
||||
IRecipeHarvester recipeHarvester,
|
||||
IRecipeManager recipeManager) {
|
||||
|
||||
@@ -60,6 +65,7 @@ namespace Orchard.Packaging.Controllers {
|
||||
_packageManager = packageManager;
|
||||
_appDataFolderRoot = appDataFolderRoot;
|
||||
_moduleService = moduleService;
|
||||
_hostEnvironment = hostEnvironment;
|
||||
_recipeHarvester = recipeHarvester;
|
||||
_recipeManager = recipeManager;
|
||||
_packagingSourceManager = packagingSourceManager;
|
||||
@@ -80,14 +86,30 @@ namespace Orchard.Packaging.Controllers {
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost, ActionName("RemoveTheme")]
|
||||
public ActionResult RemoveThemePOST(string themeId, string returnUrl, string retryUrl) {
|
||||
[HttpPost, ActionName("UninstallTheme")]
|
||||
public ActionResult UninstallThemePost(string themeId, string returnUrl, string retryUrl) {
|
||||
if (String.IsNullOrEmpty(themeId)) {
|
||||
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
|
||||
}
|
||||
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to remove themes")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
return UninstallPackage(PackageBuilder.BuildPackageId(themeId, DefaultExtensionTypes.Theme), returnUrl, retryUrl);
|
||||
}
|
||||
|
||||
[HttpPost, ActionName("UninstallModule")]
|
||||
public ActionResult UninstallModulePost(string moduleId, string returnUrl, string retryUrl) {
|
||||
if (String.IsNullOrEmpty(moduleId)) {
|
||||
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
|
||||
}
|
||||
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to remove modules")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
return UninstallPackage(PackageBuilder.BuildPackageId(moduleId, DefaultExtensionTypes.Module), returnUrl, retryUrl);
|
||||
}
|
||||
|
||||
public ActionResult AddModule(string returnUrl) {
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add modules")))
|
||||
return new HttpUnauthorizedResult();
|
||||
@@ -105,7 +127,7 @@ namespace Orchard.Packaging.Controllers {
|
||||
}
|
||||
|
||||
try {
|
||||
PackageInfo packageInfo = _packageManager.Install(packageId, version, source.FeedUrl, HostingEnvironment.MapPath("~/"));
|
||||
PackageInfo packageInfo = _packageManager.Install(packageId, version, source.FeedUrl, MapAppRoot());
|
||||
|
||||
if (DefaultExtensionTypes.IsTheme(packageInfo.ExtensionType)) {
|
||||
Services.Notifier.Information(T("The theme has been successfully installed. It can be enabled in the \"Themes\" page accessible from the menu."));
|
||||
@@ -147,7 +169,7 @@ namespace Orchard.Packaging.Controllers {
|
||||
string fullFileName = Path.Combine(_appDataFolderRoot.RootFolder, Path.GetFileName(httpPostedFileBase.FileName)).Replace(Path.DirectorySeparatorChar, '/');
|
||||
httpPostedFileBase.SaveAs(fullFileName);
|
||||
var package = new ZipPackage(fullFileName);
|
||||
PackageInfo packageInfo = _packageManager.Install(package, _appDataFolderRoot.RootFolder, HostingEnvironment.MapPath("~/"));
|
||||
PackageInfo packageInfo = _packageManager.Install(package, _appDataFolderRoot.RootFolder, MapAppRoot());
|
||||
ExtensionDescriptor extensionDescriptor = package.GetExtensionDescriptor(packageInfo.ExtensionType);
|
||||
System.IO.File.Delete(fullFileName);
|
||||
|
||||
@@ -247,20 +269,21 @@ namespace Orchard.Packaging.Controllers {
|
||||
return Redirect(redirectUrl);
|
||||
}
|
||||
|
||||
public ActionResult UninstallPackage(string id, string returnUrl, string retryUrl) {
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to uninstall packages")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
private ActionResult UninstallPackage(string id, string returnUrl, string retryUrl) {
|
||||
try {
|
||||
_packageManager.Uninstall(id, HostingEnvironment.MapPath("~/"));
|
||||
_packageManager.Uninstall(id, MapAppRoot());
|
||||
}
|
||||
catch (Exception exception) {
|
||||
Services.Notifier.Error(T("Uninstall failed: {0}", exception.Message));
|
||||
return Redirect(retryUrl);
|
||||
return Redirect(!String.IsNullOrEmpty(retryUrl) ? retryUrl : returnUrl);
|
||||
}
|
||||
|
||||
Services.Notifier.Information(T("Uninstalled package \"{0}\"", id));
|
||||
return this.RedirectLocal(returnUrl, "~/");
|
||||
}
|
||||
|
||||
private string MapAppRoot() {
|
||||
return _hostEnvironment.MapPath("~/");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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" />
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -13,15 +15,24 @@ namespace Orchard.Packaging.Services {
|
||||
public class PackageManager : IPackageManager {
|
||||
private readonly IExtensionManager _extensionManager;
|
||||
private readonly IPackageBuilder _packageBuilder;
|
||||
private readonly IPackageInstaller _packageExpander;
|
||||
private readonly IPackageInstaller _packageInstaller;
|
||||
private readonly IShellStateManager _shellStateManager;
|
||||
private readonly IFeatureManager _featureManager;
|
||||
private readonly IPackageUninstallHandler _packageUninstallHandler;
|
||||
|
||||
public PackageManager(
|
||||
IExtensionManager extensionManager,
|
||||
IPackageBuilder packageBuilder,
|
||||
IPackageInstaller packageExpander) {
|
||||
IPackageInstaller packageInstaller,
|
||||
IShellStateManager shellStateManager,
|
||||
IFeatureManager featureManager,
|
||||
IPackageUninstallHandler packageUninstallHandler) {
|
||||
_extensionManager = extensionManager;
|
||||
_packageBuilder = packageBuilder;
|
||||
_packageExpander = packageExpander;
|
||||
_packageInstaller = packageInstaller;
|
||||
_shellStateManager = shellStateManager;
|
||||
_featureManager = featureManager;
|
||||
_packageUninstallHandler = packageUninstallHandler;
|
||||
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
@@ -61,15 +72,38 @@ namespace Orchard.Packaging.Services {
|
||||
}
|
||||
|
||||
public PackageInfo Install(IPackage package, string location, string applicationPath) {
|
||||
return DoInstall(() => _packageExpander.Install(package, location, applicationPath));
|
||||
return DoInstall(() => _packageInstaller.Install(package, location, applicationPath));
|
||||
}
|
||||
|
||||
public PackageInfo Install(string packageId, string version, string location, string applicationPath) {
|
||||
return DoInstall(() => _packageExpander.Install(packageId, version, location, applicationPath));
|
||||
return DoInstall(() => _packageInstaller.Install(packageId, version, location, applicationPath));
|
||||
}
|
||||
|
||||
public void Uninstall(string packageId, string applicationPath) {
|
||||
_packageExpander.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
|
||||
|
||||
@@ -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("~/"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,25 +12,27 @@
|
||||
@T("There is no current theme in the application. The built-in theme will be used.")<br />
|
||||
@Html.ActionLink(T("Install a new Theme").ToString(), "Install")
|
||||
</p>
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
<h3 id="currentThemeTitle">@T("Current Theme")</h3>
|
||||
|
||||
@Display.ThemeEntry_Current(ContentPart: Model.CurrentTheme)
|
||||
@Display.ThemeEntry_Current(Theme: Model.CurrentTheme)
|
||||
}
|
||||
|
||||
<div id="installedBar" class="group">
|
||||
<h3>@T("Available")</h3>
|
||||
@if (Model.InstallThemes) {
|
||||
@Html.ActionLink(T("Install a theme from your computer").ToString(), "AddTheme", "PackagingServices", new { area = "Orchard.Packaging", returnUrl = HttpContext.Current.Request.RawUrl }, null)
|
||||
}
|
||||
@Html.ActionLink(T("Install a theme from your computer").ToString(), "AddTheme", "PackagingServices", new { area = "Orchard.Packaging", returnUrl = HttpContext.Current.Request.RawUrl }, null)
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (Model.Themes == null || Model.Themes.Count() <= 0) {
|
||||
<p>@T("There are no additional themes installed.")</p>
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
<ul class="templates">
|
||||
@foreach (ThemeEntry themeEntry in Model.Themes) {
|
||||
<li>@Display.ThemeEntry(ContentPart: themeEntry)</li>
|
||||
@foreach (var themeEntry in Model.Themes) {
|
||||
<li>@Display.ThemeEntry(Theme: themeEntry)</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
@@ -2,17 +2,23 @@
|
||||
@using Orchard.Mvc.Html
|
||||
@using Orchard.Environment.Extensions.Models
|
||||
|
||||
@{
|
||||
Orchard.Themes.Models.ThemeEntry theme = Model.Theme;
|
||||
}
|
||||
|
||||
<div id="currentTheme">
|
||||
@Html.Image(Href(Html.ThemePath((ExtensionDescriptor)Model.ContentPart.Descriptor, "/Theme.png")), Html.Encode((string)Model.ContentPart.Name), new { @class = "themePreviewImage" })
|
||||
@Html.Image(Href(Html.ThemePath(theme.Descriptor, "/Theme.png")), Html.Encode(theme.Name), new { @class = "themePreviewImage" })
|
||||
|
||||
<div class="details">
|
||||
<h4>@Model.ContentPart.Name</h4>
|
||||
<h5>@T("By") @Model.ContentPart.Descriptor.Author<br />
|
||||
@T("Version:") @Model.ContentPart.Descriptor.Version<br />
|
||||
@if (Model.ContentPart.Descriptor.WebSite != null) {
|
||||
<a href="@Model.ContentPart.Descriptor.WebSite">@Model.ContentPart.Descriptor.WebSite</a><br />
|
||||
}</h5>
|
||||
|
||||
<p class="themeInfo">@Model.ContentPart.Descriptor.Description</p>
|
||||
<h4>@theme.Name</h4>
|
||||
<h5>
|
||||
@T("By") @theme.Descriptor.Author<br />
|
||||
@T("Version:") @theme.Descriptor.Version<br />
|
||||
@if (theme.Descriptor.WebSite != null) {
|
||||
<a href="@theme.Descriptor.WebSite">@theme.Descriptor.WebSite</a><br />
|
||||
}
|
||||
</h5>
|
||||
|
||||
<p class="themeInfo">@theme.Descriptor.Description</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,65 +1,74 @@
|
||||
@using Orchard.Themes.Models
|
||||
@using Orchard.Mvc.Html
|
||||
@using Orchard.Environment.Extensions.Models
|
||||
@using Orchard.Utility.Extensions;
|
||||
|
||||
@{ string themeClasses = Model.ContentPart.IsRecentlyInstalled ? "recentlyInstalledTheme" : string.Empty; }
|
||||
@{
|
||||
Script.Require("ShapesBase").AtFoot();
|
||||
|
||||
Orchard.Themes.Models.ThemeEntry theme = Model.Theme;
|
||||
var themeClasses = theme.IsRecentlyInstalled ? "class=\"recentlyInstalledTheme\"" : String.Empty;
|
||||
}
|
||||
|
||||
<div>
|
||||
<h3@{ if(!string.IsNullOrEmpty(themeClasses)) {<text> class="@themeClasses"</text>}}>@Model.ContentPart.Name</h3>
|
||||
<h3 @Html.Raw(themeClasses)>@theme.Name</h3>
|
||||
|
||||
@Html.Image(Href(Html.ThemePath((ExtensionDescriptor) Model.ContentPart.Descriptor, "/Theme.png")), Html.Encode((string)Model.ContentPart.Name), null)
|
||||
@Html.Image(Href(Html.ThemePath((ExtensionDescriptor)theme.Descriptor, "/Theme.png")), Html.Encode((string)theme.Name), null)
|
||||
@using (Html.BeginFormAntiForgeryPost(Url.Action("Activate"), FormMethod.Post, new { @class = "inline" })) {
|
||||
@Html.Hidden("themeId", (string)Model.ContentPart.Descriptor.Id)
|
||||
@Html.Hidden("themeId", (string)theme.Descriptor.Id)
|
||||
<button type="submit" title="@T("Activate")">@T("Set Current")</button>
|
||||
}
|
||||
|
||||
@using (Html.BeginFormAntiForgeryPost(Url.Action("Preview"), FormMethod.Post, new { @class = "inline" })) {
|
||||
@Html.Hidden("themeId", (string)Model.ContentPart.Descriptor.Id)
|
||||
@Html.Hidden("themeId", (string)theme.Descriptor.Id)
|
||||
<button type="submit" title="@T("Preview")">@T("Preview")</button>
|
||||
}
|
||||
|
||||
<p class="themeInfo smallText">
|
||||
@T("By") @Model.ContentPart.Descriptor.Author<br />
|
||||
@T("Version:") @Model.ContentPart.Descriptor.Version<br />
|
||||
@Model.ContentPart.Descriptor.Description<br />
|
||||
@if (Model.ContentPart.Descriptor.WebSite != null) {
|
||||
<a href="@Model.ContentPart.Descriptor.WebSite">@Model.ContentPart.Descriptor.WebSite</a><br />
|
||||
@T("By") @theme.Descriptor.Author<br />
|
||||
@T("Version:") @theme.Descriptor.Version<br />
|
||||
@theme.Descriptor.Description<br />
|
||||
@if (theme.Descriptor.WebSite != null) {
|
||||
<a href="@theme.Descriptor.WebSite">@theme.Descriptor.WebSite</a><br />
|
||||
}
|
||||
</p>
|
||||
|
||||
@if (Model.ContentPart.Notifications != null && Model.ContentPart.Notifications.Count > 0) {
|
||||
@if (theme.Notifications != null && theme.Notifications.Count > 0) {
|
||||
<ul class="notifications">
|
||||
@foreach (string notification in Model.ContentPart.Notifications) {
|
||||
<li>@notification</li>
|
||||
}
|
||||
@foreach (string notification in theme.Notifications) {
|
||||
<li>@notification</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
|
||||
@if (Model.ContentPart.Enabled) {
|
||||
@if (theme.Enabled) {
|
||||
using (Html.BeginFormAntiForgeryPost(Url.Action("Disable"), FormMethod.Post, new { @class = "inline link" })) {
|
||||
@Html.Hidden("themeId", (string)Model.ContentPart.Descriptor.Id)
|
||||
@Html.Hidden("themeId", (string)theme.Descriptor.Id)
|
||||
<button type="submit" class="disable" title="Disable">@T("Disable")</button>
|
||||
}
|
||||
}
|
||||
else {
|
||||
using (Html.BeginFormAntiForgeryPost(Url.Action("Enable"), FormMethod.Post, new { @class = "inline link" })) {
|
||||
@Html.Hidden("themeId", (string)Model.ContentPart.Descriptor.Id)
|
||||
@Html.Hidden("themeId", (string)theme.Descriptor.Id)
|
||||
<button type="submit" class="enable" title="Enable">@T("Enable")</button>
|
||||
}
|
||||
}
|
||||
|
||||
@if (Model.ContentPart.NeedsUpdate) {
|
||||
@if (theme.NeedsUpdate) {
|
||||
<span> | </span>
|
||||
using (Html.BeginFormAntiForgeryPost(Url.Action("Update"), FormMethod.Post, new { @class = "inline link" })) {
|
||||
@Html.Hidden("themeId", (string)Model.ContentPart.Descriptor.Id)
|
||||
<button type="submit" class="update">@T("Update")</button> <br/>
|
||||
@Html.Hidden("themeId", (string)theme.Descriptor.Id)
|
||||
<button type="submit" class="update">@T("Update")</button> <br />
|
||||
}
|
||||
}
|
||||
|
||||
@if (Model.ContentPart.CanUninstall) {
|
||||
@if (theme.CanUninstall) {
|
||||
<span> | </span>
|
||||
using (Html.BeginFormAntiForgeryPost(Url.Action("RemoveTheme", "PackagingServices", new { area = "Orchard.Packaging", returnUrl = HttpContext.Current.Request.RawUrl, retryUrl = HttpContext.Current.Request.RawUrl, themeId = Model.ContentPart.Descriptor.Id }), FormMethod.Post, new { @class = "inline link" })) {
|
||||
<button type="submit" class="uninstall" title="@T("Uninstall")">@T("Uninstall")</button>
|
||||
}
|
||||
@Html.ActionLink(
|
||||
T("Uninstall").Text,
|
||||
"UninstallTheme",
|
||||
"PackagingServices",
|
||||
new { ThemeId = theme.Descriptor.Id, ReturnUrl = Request.ToUrlString(), Area = "Orchard.Packaging" },
|
||||
new { itemprop = "RemoveUrl UnsafeUrl" })
|
||||
}
|
||||
</div>
|
||||
Reference in New Issue
Block a user