--HG--
branch : dev
This commit is contained in:
Nathan Heskew 2010-12-01 15:55:48 -08:00
commit ca0a7e77be
15 changed files with 142 additions and 155 deletions

View File

@ -26,8 +26,8 @@ namespace Orchard.Modules.Controllers {
IReportsCoordinator reportsCoordinator,
IExtensionManager extensionManager,
IFeatureManager featureManager,
ShellDescriptor shellDescriptor) {
ShellDescriptor shellDescriptor)
{
Services = services;
_moduleService = moduleService;
_dataMigrationManager = dataMigrationManager;
@ -47,47 +47,10 @@ namespace Orchard.Modules.Controllers {
return new HttpUnauthorizedResult();
var modules = _extensionManager.AvailableExtensions().Where(x => x.ExtensionType == "Module");
return View(new ModulesIndexViewModel { Modules = modules });
}
public ActionResult Add() {
return View(new ModuleAddViewModel());
}
[HttpPost, ActionName("Add")]
public ActionResult AddPOST() {
// module not used for anything other than display (and that only to not have object in the view 'T')
var viewModel = new ModuleAddViewModel();
try {
UpdateModel(viewModel);
if (!Services.Authorizer.Authorize(Permissions.ManageModules, T("Couldn't upload module package.")))
return new HttpUnauthorizedResult();
if (string.IsNullOrWhiteSpace(Request.Files[0].FileName)) {
ModelState.AddModelError("File", T("Select a file to upload.").ToString());
}
if (!ModelState.IsValid)
return View("add", viewModel);
foreach (string fileName in Request.Files) {
var file = Request.Files[fileName];
#if REFACTORING
var info = _packageManager.Install(file.InputStream);
Services.Notifier.Information(T("Installed package \"{0}\", version {1} of type \"{2}\" at location \"{3}\"",
info.ExtensionName, info.ExtensionVersion, info.ExtensionType, info.ExtensionPath));
#endif
}
return RedirectToAction("index");
}
catch (Exception exception) {
for (var scan = exception; scan != null; scan = scan.InnerException) {
Services.Notifier.Error(T("Uploading module package failed: {0}", exception.Message));
}
return View("add", viewModel);
}
return View(new ModulesIndexViewModel {
Modules = modules,
InstallModules = _featureManager.GetEnabledFeatures().FirstOrDefault(f => f.Id == "Gallery") != null });
}
public ActionResult Features() {

View File

@ -8,4 +8,4 @@ Description: The Modules module enables the administrator of the site to manage
Features:
Orchard.Modules:
Description: Standard module and feature management.
Category: Core
Category: Core

View File

@ -62,12 +62,10 @@
<Compile Include="Permissions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Services\ModuleService.cs" />
<Compile Include="ViewModels\ModuleAddViewModel.cs" />
<Compile Include="ViewModels\ModulesIndexViewModel.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Module.txt" />
<Content Include="Views\Admin\Add.cshtml" />
<Content Include="Views\Admin\Index.cshtml" />
</ItemGroup>
<ItemGroup>
@ -75,10 +73,6 @@
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
<Name>Orchard.Framework</Name>
</ProjectReference>
<ProjectReference Include="..\Orchard.Packaging\Orchard.Packaging.csproj">
<Project>{DFD137A2-DDB5-4D22-BE0D-FA9AD4C8B059}</Project>
<Name>Orchard.Packaging</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="Content\Admin\images\disabled.gif" />

View File

@ -1,4 +0,0 @@
namespace Orchard.Modules.ViewModels {
public class ModuleAddViewModel {
}
}

View File

@ -3,6 +3,7 @@ using Orchard.Environment.Extensions.Models;
namespace Orchard.Modules.ViewModels {
public class ModulesIndexViewModel {
public bool InstallModules { get; set; }
public IEnumerable<ExtensionDescriptor> Modules { get; set; }
}
}

View File

@ -23,7 +23,7 @@
if (featureGroup == featureGroups.Last()) {
categoryClassName += " last";
}
//temporarily "disable" actions on core features
var showActions = categoryName.ToString() != "Core";
<li class="@categoryClassName">
@ -96,5 +96,4 @@
</li>}
}</ul>
</li>}
}</ul>}
}</ul>}

View File

@ -8,7 +8,11 @@
}
<h1>@Html.TitleForPage(T("Installed Modules").ToString())</h1>
<div class="manage">@Html.ActionLink(T("Install a module").ToString(), "Add", null, new { @class = "button primaryAction" })</div>
@if (Model.InstallModules) {
<div class="manage">@Html.ActionLink(T("Install a module").ToString(), "AddModule", "Gallery", new { area = "Orchard.Packaging", returnUrl = HttpContext.Current.Request.RawUrl }, new { @class = "button primaryAction" })</div>
}
@if (Model.Modules.Count() > 0) {
<ul class="contentItems">
@foreach (var module in Model.Modules.OrderBy(m => m.Name)) {
@ -20,7 +24,7 @@
<p>@module.Description</p>}
<ul class="pageStatus" style="color:#666; margin:.6em 0 0 0;">
<li>@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())))</li>
<li>&nbsp;&#124;&nbsp;@T("Author: {0}", !string.IsNullOrEmpty(module.Author) ? module.Author : (new []{"Bradley", "Bertrand", "Renaud", "Suha", "Sebastien", "Jon", "Nathan", "Erik", "Andre"})[(module.Name.Length + (new Random()).Next()) % 7])</li>
<li>&nbsp;&#124;&nbsp;@T("Author: {0}", !string.IsNullOrEmpty(module.Author) ? module.Author : "Unknown")</li>
<li>&nbsp;&#124;&nbsp;@T("Website: {0}", !string.IsNullOrEmpty(module.WebSite) ? module.WebSite : "http://orchardproject.net")</li>
</ul>
</div>

View File

@ -1,15 +1,20 @@
using System;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Hosting;
using System.Web.Mvc;
using System.Xml.Linq;
using NuGet;
using Orchard.Environment.Extensions;
using Orchard.FileSystems.AppData;
using Orchard.Localization;
using Orchard.Packaging.Services;
using Orchard.Packaging.ViewModels;
using Orchard.Themes;
using Orchard.UI.Admin;
using Orchard.UI.Notify;
using IPackageManager = Orchard.Packaging.Services.IPackageManager;
namespace Orchard.Packaging.Controllers {
[OrchardFeature("Gallery")]
@ -18,18 +23,19 @@ namespace Orchard.Packaging.Controllers {
private readonly IPackageManager _packageManager;
private readonly IPackagingSourceManager _packagingSourceManager;
private readonly IExtensionManager _extensionManager;
private readonly IAppDataFolderRoot _appDataFolderRoot;
private readonly INotifier _notifier;
public GalleryController(
IPackageManager packageManager,
IPackagingSourceManager packagingSourceManager,
IExtensionManager extensionManager,
INotifier notifier) {
INotifier notifier,
IAppDataFolderRoot appDataFolderRoot) {
_packageManager = packageManager;
_packagingSourceManager = packagingSourceManager;
_extensionManager = extensionManager;
_notifier = notifier;
_appDataFolderRoot = appDataFolderRoot;
T = NullLocalizer.Instance;
}
@ -95,7 +101,6 @@ namespace Orchard.Packaging.Controllers {
}
}
public ActionResult Modules(int? sourceId) {
var selectedSource = _packagingSourceManager.GetSources().Where(s => s.Id == sourceId).FirstOrDefault();
@ -137,5 +142,43 @@ namespace Orchard.Packaging.Controllers {
return RedirectToAction(redirectTo == "Themes" ? "Themes" : "Modules");
}
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')
try {
if (string.IsNullOrWhiteSpace(Request.Files[0].FileName)) {
ModelState.AddModelError("File", T("Select a file to upload.").ToString());
}
foreach (string fileName in Request.Files) {
HttpPostedFileBase file = Request.Files[fileName];
if (file != null) {
string fullFileName = Path.Combine(_appDataFolderRoot.RootFolder, fileName + ".nupkg").Replace(Path.DirectorySeparatorChar, '/');
file.SaveAs(fullFileName);
PackageInfo info = _packageManager.Install(new ZipPackage(fullFileName), _appDataFolderRoot.RootFolder, HostingEnvironment.MapPath("~/"));
System.IO.File.Delete(fullFileName);
_notifier.Information(T("Installed package \"{0}\", version {1} of type \"{2}\" at location \"{3}\"",
info.ExtensionName, info.ExtensionVersion, info.ExtensionType, info.ExtensionPath));
}
}
if (!string.IsNullOrEmpty(returnUrl))
return Redirect(returnUrl);
return RedirectToAction("Modules");
} catch (Exception exception) {
for (var scan = exception; scan != null; scan = scan.InnerException) {
_notifier.Error(T("Uploading module package failed: {0}", exception.Message));
}
return View("AddModule");
}
}
}
}

View File

@ -16,4 +16,4 @@ Features:
Gallery:
Description: Module gallery management.
Dependencies: PackagingServices, Orchard.Packaging
Category: Packaging
Category: Packaging

View File

@ -35,7 +35,7 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="NuGet.Core, Version=0.5.0.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="NuGet.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\lib\nuget\NuGet.Core.dll</HintPath>
</Reference>
@ -93,7 +93,9 @@
<Content Include="Views\Gallery\Sources.cshtml" />
<Content Include="Views\Web.config" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Content Include="Views\Gallery\AddModule.cshtml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
@ -118,6 +120,7 @@
<ItemGroup>
<Content Include="Views\Gallery\Themes.cshtml" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@ -1,3 +1,5 @@
using NuGet;
namespace Orchard.Packaging.Services {
public class PackageInfo {
public string ExtensionName { get; set; }
@ -7,6 +9,7 @@ namespace Orchard.Packaging.Services {
}
public interface IPackageInstaller : IDependency {
PackageInfo Install(IPackage package, string location, string applicationPath);
PackageInfo Install(string packageId, string version, string location, string applicationFolder);
void Uninstall(string packageId, string applicationFolder);
}

View File

@ -1,6 +1,9 @@
using NuGet;
namespace Orchard.Packaging.Services {
public interface IPackageManager : IDependency {
PackageData Harvest(string extensionName);
PackageInfo Install(IPackage package, string location, string applicationPath);
PackageInfo Install(string packageId, string version, string location, string applicationPath);
void Uninstall(string packageId, string applicationPath);
}

View File

@ -2,25 +2,26 @@ using System;
using System.IO;
using NuGet;
using Orchard.Environment.Extensions;
using Orchard.FileSystems.AppData;
using Orchard.Localization;
using Orchard.UI.Notify;
using NuGetPackageManager = NuGet.PackageManager;
using System.Security.Permissions;
using System.Security;
using System.Web.Hosting;
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) {
public PackageInstaller(INotifier notifier,
IExtensionManager extensionManager,
IAppDataFolderRoot appDataFolderRoot) {
_notifier = notifier;
_extensionManager = extensionManager;
_appDataFolderRoot = appDataFolderRoot;
T = NullLocalizer.Instance;
}
@ -28,44 +29,53 @@ namespace Orchard.Packaging.Services {
public Localizer T { get; set; }
public PackageInfo Install(string packageId, string version, string location, string applicationPath) {
// this logger is used to render NuGet's log on the notifier
var logger = new NugetLogger(_notifier);
// instantiates the appropriate package repository
var packageRepository = PackageRepositoryFactory.Default.CreateRepository(new PackageSource("Default", location));
IPackageRepository packageRepository = PackageRepositoryFactory.Default.CreateRepository(new PackageSource(location, "Default"));
// gets an IPackage instance from the repository
var packageVersion = String.IsNullOrEmpty(version) ? null : new Version(version);
var package = packageRepository.FindPackage(packageId, packageVersion);
if (package == null) {
if (package == null)
{
throw new ArgumentException(T("The specified package could not be found, id:{0} version:{1}", packageId, String.IsNullOrEmpty(version) ? T("No version").Text : version).Text);
}
return Install(package, packageRepository, location, applicationPath);
}
public PackageInfo Install(IPackage package, string location, string applicationPath) {
// instantiates the appropriate package repository
IPackageRepository packageRepository = PackageRepositoryFactory.Default.CreateRepository(new PackageSource(location, "Default"));
return Install(package, packageRepository, location, applicationPath);
}
protected PackageInfo Install(IPackage package, IPackageRepository packageRepository, string location, string applicationPath) {
// this logger is used to render NuGet's log on the notifier
var logger = new NugetLogger(_notifier);
bool installed = false;
// if we can access the parent directory, and the solution is inside, NuGet-install the package here
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 };
var installedPackagesPath = Path.Combine(_appDataFolderRoot.RootFolder, PackagesPath);
packageManager.InstallPackage(package, ignoreDependencies: true);
installed = true;
}
catch {
// installing the package at the solution level failed
}
try
{
var packageManager = new NuGetPackageManager(
packageRepository,
new DefaultPackagePathResolver(location),
new PhysicalFileSystem(installedPackagesPath) { Logger = logger }
) { Logger = logger };
packageManager.InstallPackage(package, ignoreDependencies: true);
installed = true;
}
catch
{
// installing the package in the appdata folder failed
}
// if the package got installed successfully, use it, otherwise use the previous repository
var sourceRepository = installed
var sourceRepository = installed
? new LocalPackageRepository(installedPackagesPath)
: packageRepository;
@ -75,12 +85,13 @@ namespace Orchard.Packaging.Services {
new DefaultPackagePathResolver(applicationPath),
project,
new ExtensionReferenceRepository(project, sourceRepository, _extensionManager)
) {Logger = logger};
) { Logger = logger };
// add the package to the project
projectManager.AddPackageReference(packageId, packageVersion);
projectManager.AddPackageReference(package.Id, package.Version);
return new PackageInfo {
return new PackageInfo
{
ExtensionName = package.Title ?? package.Id,
ExtensionVersion = package.Version.ToString(),
ExtensionType = package.Id.StartsWith("Orchard.Theme") ? "Theme" : "Module",
@ -92,59 +103,26 @@ namespace Orchard.Packaging.Services {
// this logger is used to render NuGet's log on the notifier
var logger = new NugetLogger(_notifier);
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 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 };
var sourcePackageRepository = new LocalPackageRepository(installedPackagesPath);
var project = new FileBasedProjectSystem(applicationPath) { Logger = logger };
var projectManager = new ProjectManager(
// add the package to the project
projectManager.RemovePackageReference(packageId);
var packageManager = new NuGetPackageManager(
sourcePackageRepository,
new DefaultPackagePathResolver(installedPackagesPath),
project,
new ExtensionReferenceRepository(project, sourcePackageRepository, _extensionManager)
) { Logger = logger };
new DefaultPackagePathResolver(applicationPath),
new PhysicalFileSystem(installedPackagesPath) { Logger = logger }
) { Logger = logger };
// add the package to the project
projectManager.RemovePackageReference(packageId);
var packageManager = new NuGetPackageManager(
sourcePackageRepository,
new DefaultPackagePathResolver(applicationPath),
new PhysicalFileSystem(installedPackagesPath) { Logger = logger }
) { Logger = logger };
packageManager.UninstallPackage(packageId);
}
else {
// otherwise delete the folder
string extensionPath = packageId.StartsWith("Orchard.Themes.")
? "~/Themes/" + packageId.Substring("Orchard.Theme.".Length)
: "~/Modules/" + packageId.Substring("Orchard.Module.".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 {
parentPath = null;
return false;
}
packageManager.UninstallPackage(packageId);
}
}
}

View File

@ -1,4 +1,5 @@
using System.Linq;
using NuGet;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models;
@ -33,6 +34,11 @@ namespace Orchard.Packaging.Services {
};
}
public PackageInfo Install(IPackage package, string location, string applicationPath)
{
return _packageExpander.Install(package, location, applicationPath);
}
public PackageInfo Install(string packageId, string version, string location, string applicationPath) {
return _packageExpander.Install(packageId, version, location, applicationPath);
}

View File

@ -1,12 +1,6 @@
@model ModuleAddViewModel
@using Orchard.Modules.ViewModels;
@{
Style.Require("ModulesAdmin");
}
@{
@{
<h1>@Html.TitleForPage(T("Install a Module").ToString())</h1>
using (Html.BeginFormAntiForgeryPost(Url.Action("add", new { area = "Orchard.Modules" }), FormMethod.Post, new { enctype = "multipart/form-data" })) {
using (Html.BeginFormAntiForgeryPost(Url.Action("AddModule", new { area = "Orchard.Gallery" }), FormMethod.Post, new { enctype = "multipart/form-data" })) {
Html.ValidationSummary();
<fieldset>
<label for="ModulePackage">@T("Module Package")</label>