Gallery: publish, browse, install, and download themes. Gallery displays theme thumbnail.

--HG--
branch : dev
This commit is contained in:
Dave Reed
2010-10-05 21:04:17 -07:00
parent 16feca6be1
commit a599596d44
13 changed files with 183 additions and 42 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -1,19 +1,30 @@
using System.IO;
using System;
using System.IO;
using System.Web.Mvc;
namespace PackageIndexReferenceImplementation.Controllers {
public class StreamResult : ActionResult {
public string ContentType { get; set; }
public Stream Stream { get; set; }
public DateTime? LastModifiedDate { get; set; }
public StreamResult(string contentType, Stream stream) {
public StreamResult(string contentType, Stream stream) : this(contentType, stream, null) {
}
public StreamResult(string contentType, Stream stream, DateTime? lastModified) {
ContentType = contentType;
Stream = stream;
LastModifiedDate = lastModified;
}
public override void ExecuteResult(ControllerContext context) {
context.HttpContext.Response.ContentType = ContentType;
Stream.CopyTo(context.HttpContext.Response.OutputStream);
var response = context.HttpContext.Response;
response.ContentType = ContentType;
if (LastModifiedDate.HasValue) {
response.Cache.SetLastModified(LastModifiedDate.Value);
response.Cache.SetCacheability(System.Web.HttpCacheability.Public);
}
Stream.CopyTo(response.OutputStream);
}
}
}

View File

@@ -45,7 +45,7 @@ namespace PackageIndexReferenceImplementation.Controllers {
var password = Encoding.UTF8.GetString(Convert.FromBase64String(HttpContext.Request.Headers["Password"]));
if ( !FormsAuthentication.Authenticate(user, password) ) {
throw new AuthenticationException("This credentials are not valid fo this action.");
throw new AuthenticationException("This credentials are not valid for this action.");
}
var utcNowDateString = DateTimeOffset.UtcNow.ToString("yyyy-MM-dd");
@@ -74,7 +74,8 @@ namespace PackageIndexReferenceImplementation.Controllers {
}
private string UpdateSyndicationItem(PackageProperties packageProperties, SyndicationItem item) {
if (!string.IsNullOrEmpty(packageProperties.Category)) {
if (!string.IsNullOrEmpty(packageProperties.Creator)) {
item.Authors.Clear();
//parse package.PackageProperties.Creator into email-style authors
item.Authors.Add(new SyndicationPerson { Name = packageProperties.Creator });
@@ -85,6 +86,11 @@ namespace PackageIndexReferenceImplementation.Controllers {
item.Categories.Add(new SyndicationCategory(packageProperties.Category));
}
var contentType = packageProperties.ContentType;
if (!item.Categories.Any(c => c.Name == contentType)) {
item.Categories.Add(new SyndicationCategory(contentType));
}
if (packageProperties.Modified.HasValue) {
item.LastUpdatedTime = new DateTimeOffset(packageProperties.Modified.Value);
}
@@ -97,15 +103,16 @@ namespace PackageIndexReferenceImplementation.Controllers {
item.Summary = new TextSyndicationContent(packageProperties.Description);
}
if (!string.IsNullOrEmpty(packageProperties.Title)) {
item.Title = new TextSyndicationContent(packageProperties.Title);
}
var mediaIdentifier = packageProperties.Identifier + "-" + packageProperties.Version + ".zip";
var mediaUrl = Url.Action("Resource", "Media", new RouteValueDictionary { { "Id", mediaIdentifier }, { "ContentType", "application/x-package" } });
item.Links.Clear();
item.Links.Add(new SyndicationLink(new Uri(HostBaseUri(), new Uri(mediaUrl, UriKind.Relative))));
if (contentType == "Orchard Theme") {
var previewUrl = Url.Action("PreviewTheme", "Media", new RouteValueDictionary { { "Id", mediaIdentifier }, { "ContentType", "application/x-package" } });
item.Links.Add(new SyndicationLink(new Uri(HostBaseUri(), new Uri(previewUrl, UriKind.Relative)), "thumbnail", null, null, 0));
}
return mediaIdentifier;
}

View File

@@ -1,23 +1,49 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Web;
using System.Web.Hosting;
using System.Web.Mvc;
using PackageIndexReferenceImplementation.Services;
namespace PackageIndexReferenceImplementation.Controllers
{
public class MediaController : Controller
{
namespace PackageIndexReferenceImplementation.Controllers {
public class MediaController : Controller {
private readonly MediaStorage _mediaStorage;
public MediaController() {
_mediaStorage = new MediaStorage();
}
public ActionResult Resource(string id, string contentType)
{
public ActionResult Resource(string id, string contentType) {
return new StreamResult(contentType, _mediaStorage.GetMedia(id + ":" + contentType));
}
public ActionResult PreviewTheme(string id, string contentType) {
var stream = _mediaStorage.GetMedia(id + ":" + contentType);
var package = Package.Open(stream, FileMode.Open, FileAccess.Read);
if (package.PackageProperties.ContentType != "Orchard Theme") {
return new HttpNotFoundResult();
}
var themeName = package.PackageProperties.Identifier;
var previewUri = new Uri("/" + themeName + "/Theme.png", UriKind.Relative);
Stream previewStream;
DateTime lastModified;
if (package.PartExists(previewUri)) {
lastModified = _mediaStorage.GetLastModifiedDate(id);
previewStream = package.GetPart(new Uri("/" + themeName + "/Theme.png", UriKind.Relative)).GetStream();
}
else {
var defaultPreviewPath = HostingEnvironment.MapPath("~/Content/DefaultThemePreview.png");
if (defaultPreviewPath == null || !System.IO.File.Exists(defaultPreviewPath)) {
return new HttpNotFoundResult();
}
lastModified = System.IO.File.GetLastWriteTimeUtc(defaultPreviewPath);
previewStream = System.IO.File.Open(defaultPreviewPath, FileMode.Open, FileAccess.Read);
}
return new StreamResult("image/png", previewStream, lastModified);
}
}
}

View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PackageIndexReferenceImplementation", "PackageIndexReferenceImplementation.csproj", "{8A4E42CE-79F8-4BE2-8B1E-A6B83432123B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8A4E42CE-79F8-4BE2-8B1E-A6B83432123B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A4E42CE-79F8-4BE2-8B1E-A6B83432123B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A4E42CE-79F8-4BE2-8B1E-A6B83432123B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A4E42CE-79F8-4BE2-8B1E-A6B83432123B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -1,4 +1,5 @@
using System.IO;
using System;
using System.IO;
using System.Linq;
using System.Web.Hosting;
@@ -25,6 +26,15 @@ namespace PackageIndexReferenceImplementation.Services {
return new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
}
public DateTime GetLastModifiedDate(string identifier) {
if (!Directory.Exists(HostingEnvironment.MapPath("~/App_Data/Media")))
Directory.CreateDirectory(HostingEnvironment.MapPath("~/App_Data/Media"));
var safeIdentifier = GetSafeIdentifier(identifier);
var filePath = HostingEnvironment.MapPath("~/App_Data/Media/" + safeIdentifier);
return File.GetLastWriteTimeUtc(filePath);
}
static string GetSafeIdentifier(string identifier) {
var invalidFileNameChars = Path.GetInvalidFileNameChars().Concat(Path.GetInvalidPathChars()).Distinct();
var safeIdentifier = identifier.Replace("^", string.Format("^{0:X2}", (int)'^'));