diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Index.cshtml
index 789c389e8..54645d17f 100644
--- a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Index.cshtml
+++ b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Index.cshtml
@@ -24,7 +24,7 @@
@module.Description
}
- @T("Features: {0}", MvcHtmlString.Create(string.Join(", ", module.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())))
- - | @T("Author: {0}", !string.IsNullOrEmpty(module.Author) ? module.Author : "Unknown")
+ - | @T("Author: {0}", !string.IsNullOrEmpty(module.Author) ? module.Author : T("Unknown").ToString())
- | @T("Website: {0}", !string.IsNullOrEmpty(module.WebSite) ? module.WebSite : "http://orchardproject.net")
diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryController.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryController.cs
index 3bf4341b2..1e4607f00 100644
--- a/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryController.cs
+++ b/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryController.cs
@@ -6,6 +6,7 @@ using System.Web.Hosting;
using System.Web.Mvc;
using System.Xml.Linq;
using NuGet;
+using Orchard.Environment;
using Orchard.Environment.Extensions;
using Orchard.FileSystems.AppData;
using Orchard.Localization;
@@ -25,16 +26,19 @@ namespace Orchard.Packaging.Controllers {
private readonly IPackagingSourceManager _packagingSourceManager;
private readonly IAppDataFolderRoot _appDataFolderRoot;
private readonly INotifier _notifier;
+ private readonly IHostEnvironment _hostEnvironment;
public GalleryController(
IPackageManager packageManager,
IPackagingSourceManager packagingSourceManager,
INotifier notifier,
- IAppDataFolderRoot appDataFolderRoot) {
+ IAppDataFolderRoot appDataFolderRoot,
+ IHostEnvironment hostEnvironment) {
_packageManager = packageManager;
_packagingSourceManager = packagingSourceManager;
_notifier = notifier;
_appDataFolderRoot = appDataFolderRoot;
+ _hostEnvironment = hostEnvironment;
T = NullLocalizer.Instance;
}
@@ -60,12 +64,11 @@ namespace Orchard.Packaging.Controllers {
[HttpPost]
public ActionResult AddSource(string url) {
try {
- if ( !String.IsNullOrEmpty(url) ) {
+ if (!String.IsNullOrEmpty(url)) {
if (!url.StartsWith("http")) {
ModelState.AddModelError("Url", T("The Url is not valid").Text);
}
- }
- else if ( String.IsNullOrWhiteSpace(url)) {
+ } else if (String.IsNullOrWhiteSpace(url)) {
ModelState.AddModelError("Url", T("Url is required").Text);
}
@@ -73,29 +76,27 @@ namespace Orchard.Packaging.Controllers {
// try to load the feed
try {
- XNamespace atomns = "http://www.w3.org/2005/Atom" ;
+ XNamespace atomns = "http://www.w3.org/2005/Atom";
var feed = XDocument.Load(url, LoadOptions.PreserveWhitespace);
var titleNode = feed.Descendants(atomns + "title").FirstOrDefault();
- if ( titleNode != null )
+ if (titleNode != null)
title = titleNode.Value;
- if(String.IsNullOrWhiteSpace(title)) {
+ if (String.IsNullOrWhiteSpace(title)) {
ModelState.AddModelError("Url", T("The feed has no title.").Text);
}
- }
- catch {
+ } catch {
ModelState.AddModelError("Url", T("The url of the feed or its content is not valid.").Text);
}
- if ( !ModelState.IsValid )
+ if (!ModelState.IsValid)
return View(new PackagingAddSourceViewModel { Url = url });
_packagingSourceManager.AddSource(title, url);
_notifier.Information(T("The feed has been added successfully."));
return RedirectToAction("Sources");
- }
- catch ( Exception exception ) {
+ } catch (Exception exception) {
_notifier.Error(T("Adding feed failed: {0}", exception.Message));
return View(new PackagingAddSourceViewModel { Url = url });
}
@@ -104,8 +105,8 @@ namespace Orchard.Packaging.Controllers {
public ActionResult Modules(int? sourceId) {
var selectedSource = _packagingSourceManager.GetSources().Where(s => s.Id == sourceId).FirstOrDefault();
- var sources = selectedSource != null
- ? new [] { selectedSource }
+ var sources = selectedSource != null
+ ? new[] { selectedSource }
: _packagingSourceManager.GetSources()
;
@@ -134,7 +135,7 @@ namespace Orchard.Packaging.Controllers {
public ActionResult Install(string packageId, string version, int sourceId, string redirectTo) {
var source = _packagingSourceManager.GetSources().Where(s => s.Id == sourceId).FirstOrDefault();
- if(source == null) {
+ if (source == null) {
return HttpNotFound();
}
@@ -147,15 +148,30 @@ namespace Orchard.Packaging.Controllers {
return View();
}
+ [HttpPost, ActionName("AddTheme")]
+ public ActionResult AddThemePOST(string returnUrl) {
+ return InstallPackage(returnUrl, Request.RawUrl);
+ }
+
+ [HttpPost, ActionName("RemoveTheme")]
+ public ActionResult RemoveThemePOST(string themeId, string returnUrl, string retryUrl) {
+ return UninstallPackage(PackagingSourceManager.ThemesFilter + themeId, returnUrl, retryUrl);
+ }
+
public ActionResult AddModule(string returnUrl) {
return View();
}
[HttpPost, ActionName("AddModule")]
public ActionResult AddModulePOST(string returnUrl) {
- // module not used for anything o2ther than display (and that only to not have object in the view 'T')
+ return InstallPackage(returnUrl, Request.RawUrl);
+ }
+
+ public ActionResult InstallPackage(string returnUrl, string retryUrl) {
try {
- if (string.IsNullOrWhiteSpace(Request.Files[0].FileName)) {
+ if (Request.Files != null &&
+ Request.Files.Count > 0 &&
+ !string.IsNullOrWhiteSpace(Request.Files[0].FileName)) {
ModelState.AddModelError("File", T("Select a file to upload.").ToString());
}
@@ -172,16 +188,29 @@ namespace Orchard.Packaging.Controllers {
}
}
- if (!string.IsNullOrEmpty(returnUrl))
- return Redirect(returnUrl);
-
- return RedirectToAction("Modules");
+ return Redirect(returnUrl);
} catch (Exception exception) {
- for (var scan = exception; scan != null; scan = scan.InnerException) {
+ for (Exception scan = exception; scan != null; scan = scan.InnerException) {
_notifier.Error(T("Uploading module package failed: {0}", exception.Message));
}
- return View("AddModule");
+ return Redirect(retryUrl);
+ }
+ }
+
+ public ActionResult UninstallPackage(string id, string returnUrl, string retryUrl) {
+ try {
+ _packageManager.Uninstall(id, HostingEnvironment.MapPath("~/"));
+
+ _notifier.Information(T("Uninstalled package \"{0}\"", id));
+
+ return Redirect(returnUrl);
+ } catch (Exception exception) {
+ for (Exception scan = exception; scan != null; scan = scan.InnerException) {
+ _notifier.Error(T("Uninstall failed: {0}", exception.Message));
+ }
+
+ return Redirect(retryUrl);
}
}
}
diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageInstaller.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageInstaller.cs
index 22c2f0497..a390ca9a7 100644
--- a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageInstaller.cs
+++ b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageInstaller.cs
@@ -1,9 +1,9 @@
using System;
using System.IO;
+using System.Web.Hosting;
using NuGet;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models;
-using Orchard.FileSystems.AppData;
using Orchard.Localization;
using Orchard.UI.Notify;
using NuGetPackageManager = NuGet.PackageManager;
@@ -12,17 +12,15 @@ namespace Orchard.Packaging.Services {
[OrchardFeature("PackagingServices")]
public class PackageInstaller : IPackageInstaller {
private const string PackagesPath = "packages";
+ private const string SolutionFilename = "Orchard.sln";
private readonly INotifier _notifier;
private readonly IExtensionManager _extensionManager;
- private readonly IAppDataFolderRoot _appDataFolderRoot;
public PackageInstaller(INotifier notifier,
- IExtensionManager extensionManager,
- IAppDataFolderRoot appDataFolderRoot) {
+ IExtensionManager extensionManager) {
_notifier = notifier;
_extensionManager = extensionManager;
- _appDataFolderRoot = appDataFolderRoot;
T = NullLocalizer.Instance;
}
@@ -57,22 +55,23 @@ namespace Orchard.Packaging.Services {
bool installed = false;
// if we can access the parent directory, and the solution is inside, NuGet-install the package here
- var installedPackagesPath = Path.Combine(_appDataFolderRoot.RootFolder, PackagesPath);
-
- try
- {
- var packageManager = new NuGetPackageManager(
+ string solutionPath;
+ var installedPackagesPath = String.Empty;
+ if (TryGetSolutionPath(applicationPath, out solutionPath)) {
+ installedPackagesPath = Path.Combine(solutionPath, PackagesPath);
+ try {
+ var packageManager = new NuGetPackageManager(
packageRepository,
new DefaultPackagePathResolver(location),
- new PhysicalFileSystem(installedPackagesPath) { Logger = logger }
- ) { Logger = logger };
+ new PhysicalFileSystem(installedPackagesPath) {Logger = logger}
+ ) {Logger = logger};
- packageManager.InstallPackage(package, ignoreDependencies: true);
- installed = true;
- }
- catch
- {
- // installing the package in the appdata folder failed
+ packageManager.InstallPackage(package, true);
+ installed = true;
+ }
+ catch {
+ // installing the package at the solution level failed
+ }
}
// if the package got installed successfully, use it, otherwise use the previous repository
@@ -95,7 +94,7 @@ namespace Orchard.Packaging.Services {
{
ExtensionName = package.Title ?? package.Id,
ExtensionVersion = package.Version.ToString(),
- ExtensionType = package.Id.StartsWith("Orchard.Theme") ? DefaultExtensionTypes.Theme : DefaultExtensionTypes.Module,
+ ExtensionType = package.Id.StartsWith(PackagingSourceManager.ThemesFilter) ? DefaultExtensionTypes.Theme : DefaultExtensionTypes.Module,
ExtensionPath = applicationPath
};
}
@@ -104,26 +103,58 @@ namespace Orchard.Packaging.Services {
// this logger is used to render NuGet's log on the notifier
var logger = new NugetLogger(_notifier);
- var installedPackagesPath = Path.Combine(_appDataFolderRoot.RootFolder, PackagesPath);
- var sourcePackageRepository = new LocalPackageRepository(installedPackagesPath);
- var project = new FileBasedProjectSystem(applicationPath) { Logger = logger };
- var projectManager = new ProjectManager(
- sourcePackageRepository,
- new DefaultPackagePathResolver(installedPackagesPath),
- project,
- new ExtensionReferenceRepository(project, sourcePackageRepository, _extensionManager)
- ) { Logger = logger };
+ string solutionPath;
+ // if we can access the parent directory, and the solution is inside, NuGet-uninstall the package here
+ if (TryGetSolutionPath(applicationPath, out solutionPath)) {
+ var installedPackagesPath = Path.Combine(solutionPath, PackagesPath);
+ var sourcePackageRepository = new LocalPackageRepository(installedPackagesPath);
+ var project = new FileBasedProjectSystem(applicationPath) { Logger = logger };
+ var projectManager = new ProjectManager(
+ sourcePackageRepository,
+ new DefaultPackagePathResolver(installedPackagesPath),
+ project,
+ new ExtensionReferenceRepository(project, sourcePackageRepository, _extensionManager)
+ ) { Logger = logger };
- // add the package to the project
- projectManager.RemovePackageReference(packageId);
+ // add the package to the project
+ projectManager.RemovePackageReference(packageId);
- var packageManager = new NuGetPackageManager(
+ var packageManager = new NuGetPackageManager(
sourcePackageRepository,
new DefaultPackagePathResolver(applicationPath),
new PhysicalFileSystem(installedPackagesPath) { Logger = logger }
- ) { Logger = logger };
+ ) { Logger = logger };
- packageManager.UninstallPackage(packageId);
+ packageManager.UninstallPackage(packageId);
+ } else {
+ // otherwise delete the folder
+
+ string extensionPath = packageId.StartsWith(PackagingSourceManager.ThemesFilter)
+ ? "~/Themes/" + packageId.Substring(PackagingSourceManager.ThemesFilter.Length)
+ : "~/Modules/" + packageId.Substring(PackagingSourceManager.ModulesFilter.Length);
+
+ string extensionFullPath = HostingEnvironment.MapPath(extensionPath);
+
+ if (Directory.Exists(extensionFullPath)) {
+ Directory.Delete(extensionFullPath, true);
+ }
+ else {
+ throw new OrchardException(T("Package not found: ", packageId));
+ }
+ }
+ }
+
+ private bool TryGetSolutionPath(string applicationPath, out string parentPath) {
+ try {
+ parentPath = Directory.GetParent(applicationPath).Parent.FullName;
+ var solutionPath = Path.Combine(parentPath, SolutionFilename);
+ return File.Exists(solutionPath);
+ }
+ catch {
+ // Either solution does not exist or we are running under medium trust
+ parentPath = null;
+ return false;
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageManager.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageManager.cs
index 9cd833854..92eda4470 100644
--- a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageManager.cs
+++ b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageManager.cs
@@ -46,6 +46,7 @@ namespace Orchard.Packaging.Services {
public void Uninstall(string packageId, string applicationPath) {
_packageExpander.Uninstall(packageId, applicationPath);
}
+
#endregion
}
}
\ No newline at end of file
diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackagingSourceManager.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackagingSourceManager.cs
index a8f3aa7d9..4780a9535 100644
--- a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackagingSourceManager.cs
+++ b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackagingSourceManager.cs
@@ -10,8 +10,8 @@ using Orchard.Packaging.Models;
namespace Orchard.Packaging.Services {
[OrchardFeature("Gallery")]
public class PackagingSourceManager : IPackagingSourceManager {
- private const string ModulesFilter = "Orchard.Module.";
- private const string ThemesFilter = "Orchard.Theme.";
+ public const string ModulesFilter = "Orchard.Module.";
+ public const string ThemesFilter = "Orchard.Theme.";
private readonly IRepository _packagingSourceRecordRepository;
diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Views/Gallery/AddTheme.cshtml b/src/Orchard.Web/Modules/Orchard.Packaging/Views/Gallery/AddTheme.cshtml
index d83b0a2ce..01bff8201 100644
--- a/src/Orchard.Web/Modules/Orchard.Packaging/Views/Gallery/AddTheme.cshtml
+++ b/src/Orchard.Web/Modules/Orchard.Packaging/Views/Gallery/AddTheme.cshtml
@@ -1,10 +1,11 @@
-@Html.TitleForPage(T("Install Theme").ToString())
-@using (Html.BeginForm("Install", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" })) {
- @Html.ValidationSummary()
-
-}
+@{
+ @Html.TitleForPage(T("Install a Theme").ToString())
+ using (Html.BeginFormAntiForgeryPost(Url.Action("AddTheme", new { area = "Orchard.Gallery" }), FormMethod.Post, new { enctype = "multipart/form-data" })) {
+ Html.ValidationSummary();
+
+
+ }
+}
\ No newline at end of file
diff --git a/src/Orchard.Web/Modules/Orchard.Themes/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.Themes/Views/Admin/Index.cshtml
index bfd026f26..e84d5c3e9 100644
--- a/src/Orchard.Web/Modules/Orchard.Themes/Views/Admin/Index.cshtml
+++ b/src/Orchard.Web/Modules/Orchard.Themes/Views/Admin/Index.cshtml
@@ -19,7 +19,7 @@
if (Model.InstallThemes) {
- @Html.ActionLink(T("Install a new Theme").ToString(), "Install", null, new { @class = "button primaryAction" })
+ @Html.ActionLink(T("Install a new Theme").ToString(), "AddTheme", "Gallery", new { area = "Orchard.Packaging", returnUrl = HttpContext.Current.Request.RawUrl }, new { @class = "button primaryAction" })
}
}
@@ -55,11 +55,13 @@
}
}
- @using (Html.BeginFormAntiForgeryPost(Url.Action("Uninstall"), FormMethod.Post, new { @class = "inline link" })) {
- @Html.Hidden("themeName", theme.Id)
-
+
+ @if (Model.InstallThemes) {
+ using (Html.BeginFormAntiForgeryPost(Url.Action("RemoveTheme", "Gallery", new { area = "Orchard.Packaging", returnUrl = HttpContext.Current.Request.RawUrl, retryUrl = HttpContext.Current.Request.RawUrl, themeId = theme.Id }), FormMethod.Post, new { @class = "inline link" })) {
+
+ }
}
-
+
}
}