--HG--
branch : dev
This commit is contained in:
Renaud Paquay
2010-10-06 16:12:11 -07:00
38 changed files with 545 additions and 122 deletions

View File

@@ -14,6 +14,10 @@ namespace Orchard.Tests.Stubs {
return Directory.GetDirectories(path);
}
public IEnumerable<string> ListFiles(string path, bool recursive) {
throw new NotImplementedException();
}
public bool FileExists(string virtualPath) {
throw new NotImplementedException();
}

View File

@@ -64,7 +64,6 @@ namespace Orchard.Core.Shapes {
var zone = context.New.Zone();
zone.Id = "zone-" + name;
zone.Classes.Add(zone.Id);
zone.Classes.Add("zone");
return zone;
}

View File

@@ -15,7 +15,7 @@
@//Model.Zones.AddRenderPartial("head:before", "HeadPreload", Model);
@//Html.Zone("head", ":metas :styles :scripts"); %>
@Display(Model.Head)
<script>(function(d){d.className="dyn "+d.className.substring(7,d.length);})(document.documentElement);</script>
<script>(function(d){d.className="dyn"+d.className.substring(6,d.className.length);})(document.documentElement);</script>
</head>
<body>
@Display(Model.Body)

View File

@@ -20,10 +20,10 @@ namespace Orchard.CodeGeneration.Commands {
private readonly ISchemaCommandGenerator _schemaCommandGenerator;
private static readonly string[] _ignoredExtensions = new [] {
"dll", "obj", "pdb", "exclude"
"obj", "pdb", "exclude"
};
private static readonly string[] _ignoredPaths = new [] {
"/bin/", "/obj/"
"/obj/"
};
private static readonly string[] _themeDirectories = new [] {
"", "Content", "Styles", "Scripts", "Views", "Zones"

View File

@@ -11,9 +11,11 @@ namespace Orchard.Packaging {
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Gallery"), "5", menu => menu
.Add(T("Browse Gallery"), "1.0", item => item
.Action("Index", "Gallery", new { area = "Orchard.Packaging" }))
.Add(T("Gallery Feeds"), "2.0", item => item
.Add(T("Browse Modules"), "1.0", item => item
.Action("ModulesIndex", "Gallery", new { area = "Orchard.Packaging" }))
.Add(T("Browse Themes"), "2.0", item => item
.Action("ThemesIndex", "Gallery", new { area = "Orchard.Packaging" }))
.Add(T("Gallery Feeds"), "3.0", item => item
.Action("Sources", "Gallery", new { area = "Orchard.Packaging" })));
}
}

View File

@@ -63,7 +63,10 @@ namespace Orchard.Packaging.Commands {
Context.Output.WriteLine(T("Success"));
}
catch (WebException webException) {
var text = new StreamReader(webException.Response.GetResponseStream()).ReadToEnd();
string text = "";
if (webException.Response != null) {
text = new StreamReader(webException.Response.GetResponseStream()).ReadToEnd();
}
throw new ApplicationException(text);
}
}

View File

@@ -38,7 +38,7 @@ namespace Orchard.Packaging.Commands {
}
[CommandHelp("package install <filename>\r\n\t" + "Install a module from a package <filename>.")]
[CommandName("package install ")]
[CommandName("package install")]
public void InstallPackage(string filename) {
if (!File.Exists(filename)) {
Context.Output.WriteLine(T("File \"{0}\" does not exist.", filename));

View File

@@ -34,10 +34,14 @@ namespace Orchard.Packaging.Controllers {
Localizer T { get; set; }
public ActionResult Index() {
public ActionResult ModulesIndex() {
return Modules(Guid.Empty);
}
public ActionResult ThemesIndex() {
return Themes(Guid.Empty);
}
public ActionResult Sources() {
return View("Sources", new PackagingSourcesViewModel {
Sources = _packagingSourceManager.GetSources(),
@@ -47,7 +51,7 @@ namespace Orchard.Packaging.Controllers {
public ActionResult Remove(Guid id) {
_packagingSourceManager.RemoveSource(id);
_notifier.Information(T("The feed has been removed successfully."));
Update();
Update(null);
return RedirectToAction("Sources");
}
@@ -90,7 +94,7 @@ namespace Orchard.Packaging.Controllers {
_packagingSourceManager.AddSource(new PackagingSource { Id = Guid.NewGuid(), FeedUrl = url, FeedTitle = title });
_notifier.Information(T("The feed has been added successfully."));
Update();
Update(null);
return RedirectToAction("Sources");
}
catch ( Exception exception ) {
@@ -102,18 +106,28 @@ namespace Orchard.Packaging.Controllers {
public ActionResult Modules(Guid? sourceId) {
var selectedSource = _packagingSourceManager.GetSources().Where(s => s.Id == sourceId).FirstOrDefault();
return View("Modules", new PackagingModulesViewModel {
Modules = _packagingSourceManager.GetModuleList(selectedSource),
Modules = _packagingSourceManager.GetModuleList(selectedSource).Where(p => p.SyndicationItem.Categories.All(c => c.Name == "Orchard Module" || c.Name != "Orchard Theme")),
Sources = _packagingSourceManager.GetSources().OrderBy(s => s.FeedTitle),
SelectedSource = selectedSource
});
}
public ActionResult Update() {
public ActionResult Themes(Guid? sourceId) {
var selectedSource = _packagingSourceManager.GetSources().Where(s => s.Id == sourceId).FirstOrDefault();
return View("Themes", new PackagingModulesViewModel {
Modules = _packagingSourceManager.GetModuleList(selectedSource).Where(p => p.SyndicationItem.Categories.Any(c => c.Name == "Orchard Theme")),
Sources = _packagingSourceManager.GetSources().OrderBy(s => s.FeedTitle),
SelectedSource = selectedSource
});
}
public ActionResult Update(string cameFrom) {
_packagingSourceManager.UpdateLists();
_notifier.Information(T("List of available modules and themes is updated."));
return RedirectToAction("Index");
return RedirectToAction(cameFrom == "Themes" ? "ThemesIndex" : "ModulesIndex");
}
public ActionResult Harvest(string extensionName, string feedUrl) {
@@ -147,16 +161,16 @@ namespace Orchard.Packaging.Controllers {
_packageManager.Push(packageData, model.FeedUrl, model.User, model.Password);
_notifier.Information(T("Harvested {0} and published onto {1}", model.ExtensionName, model.FeedUrl));
Update();
Update(null);
return RedirectToAction("Harvest", new { model.ExtensionName, model.FeedUrl });
}
public ActionResult Install(string syndicationId) {
public ActionResult Install(string syndicationId, string cameFrom) {
var packageData = _packageManager.Download(syndicationId);
_packageManager.Install(packageData.PackageStream);
_notifier.Information(T("Installed module"));
return RedirectToAction("Modules");
return RedirectToAction(cameFrom == "Themes" ? "ThemesIndex" : "ModulesIndex");
}
}
}

View File

@@ -121,6 +121,9 @@
<ItemGroup>
<Content Include="Web.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Gallery\Themes.cshtml" />
</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

@@ -5,6 +5,8 @@ using System.IO.Packaging;
using System.Linq;
using System.Net.Mime;
using System.Reflection;
using System.Web;
using System.Web.Hosting;
using System.Xml.Linq;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models;
@@ -16,6 +18,19 @@ namespace Orchard.Packaging.Services {
private readonly IExtensionManager _extensionManager;
private readonly IWebSiteFolder _webSiteFolder;
private static readonly string[] _ignoredThemeExtensions = new[] {
"obj", "pdb", "exclude"
};
private static readonly string[] _ignoredThemePaths = new[] {
"/obj/"
};
private static bool IgnoreFile(string filePath) {
return String.IsNullOrEmpty(filePath) ||
_ignoredThemePaths.Any(filePath.Contains) ||
_ignoredThemeExtensions.Contains(Path.GetExtension(filePath) ?? "");
}
public PackageBuilder(IExtensionManager extensionManager, IWebSiteFolder webSiteFolder) {
_extensionManager = extensionManager;
_webSiteFolder = webSiteFolder;
@@ -27,7 +42,7 @@ namespace Orchard.Packaging.Services {
var context = new CreateContext();
BeginPackage(context);
try {
EstablishPaths(context, _webSiteFolder, extensionDescriptor.Location, extensionDescriptor.Name);
EstablishPaths(context, _webSiteFolder, extensionDescriptor.Location, extensionDescriptor.Name, extensionDescriptor.ExtensionType);
SetCoreProperties(context, extensionDescriptor);
string projectFile = extensionDescriptor.Name + ".csproj";
@@ -36,6 +51,10 @@ namespace Orchard.Packaging.Services {
EmbedProjectFiles(context, "Compile", "Content", "None", "EmbeddedResource");
EmbedReferenceFiles(context);
}
else if (extensionDescriptor.ExtensionType == "Theme") {
// this is a simple theme with no csproj
EmbedThemeFiles(context);
}
}
finally {
EndPackage(context);
@@ -110,6 +129,21 @@ namespace Orchard.Packaging.Services {
}
}
private void EmbedThemeFiles(CreateContext context) {
var basePath = context.SourcePath;
foreach (var virtualPath in context.SourceFolder.ListFiles(context.SourcePath, true)) {
// ignore dlls, etc
if (IgnoreFile(virtualPath)) {
continue;
}
// full virtual path given but we need the relative path so it can be put into
// the package that way (the package itself is the logical base path).
// Get it by stripping the basePath off including the slash.
var relativePath = virtualPath.Replace(basePath, "");
EmbedVirtualFile(context, relativePath, MediaTypeNames.Application.Octet);
}
}
private XName Ns(string localName) {
return XName.Get(localName, "http://schemas.microsoft.com/developer/msbuild/2003");
}
@@ -120,9 +154,14 @@ namespace Orchard.Packaging.Services {
context.Package = Package.Open(context.Stream, FileMode.Create, FileAccess.ReadWrite);
}
private static void EstablishPaths(CreateContext context, IWebSiteFolder webSiteFolder, string locationPath, string moduleName) {
private static void EstablishPaths(CreateContext context, IWebSiteFolder webSiteFolder, string locationPath, string moduleName, string moduleType) {
context.SourceFolder = webSiteFolder;
context.SourcePath = "~/Modules/" + moduleName + "/";
if (moduleType == "Theme") {
context.SourcePath = "~/Themes/" + moduleName + "/";
}
else {
context.SourcePath = "~/Modules/" + moduleName + "/";
}
context.TargetPath = "\\" + moduleName + "\\";
}

View File

@@ -38,6 +38,10 @@ namespace Orchard.Packaging.Services {
ExtractProjectFiles(context, "Compile", "Content", "None", "EmbeddedResource");
ExtractReferenceFiles(context);
}
else if (context.ExtensionType == "Theme") {
// this is a simple theme with no csproj
ExtractThemeFiles(context);
}
}
finally {
EndPackage(context);
@@ -108,6 +112,14 @@ namespace Orchard.Packaging.Services {
}
}
private void ExtractThemeFiles(ExpandContext context) {
foreach (var relativePath in from p in context.Package.GetParts()
where p.Uri.ToString().StartsWith("/" + context.ExtensionName + "/", StringComparison.OrdinalIgnoreCase)
select p.Uri.ToString().Substring(("/" + context.ExtensionName + "/").Length)) {
ExtractFile(context, relativePath);
}
}
private bool PartExists(ExpandContext context, string relativePath) {
Uri projectUri = PackUriHelper.CreatePartUri(new Uri(context.SourcePath + relativePath, UriKind.Relative));
return context.Package.PartExists(projectUri);

View File

@@ -53,7 +53,7 @@ namespace Orchard.Packaging.Services {
}
public IEnumerable<PackagingEntry> GetModuleList(PackagingSource packagingSource = null) {
IEnumerable<PackagingEntry> packageInfos = ( packagingSource == null ? GetSources() : new[] { packagingSource } )
return (packagingSource == null ? GetSources() : new[] {packagingSource})
.SelectMany(
source =>
Bind(ParseFeed(GetModuleListForSource(source)),
@@ -64,11 +64,8 @@ namespace Orchard.Packaging.Services {
Source = source,
SyndicationFeed = feed,
SyndicationItem = item,
PackageStreamUri = item.Links.Single().GetAbsoluteUri().AbsoluteUri,
}))));
return packageInfos.ToArray();
PackageStreamUri = item.Links.Where(l => String.IsNullOrEmpty(l.RelationshipType)).FirstOrDefault().GetAbsoluteUri().AbsoluteUri,
})))).ToArray();
}
private string GetModuleListForSource(PackagingSource source) {

View File

@@ -1,9 +1,9 @@
@model Orchard.Packaging.ViewModels.PackagingModulesViewModel
@{ Style.Require("PackagingAdmin"); }
<h1>@Html.TitleForPage(T("Browse Gallery").ToString())</h1>
<h1>@Html.TitleForPage(T("Browse Gallery - Modules").ToString())</h1>
<div class="manage">@Html.ActionLink(T("Refresh").ToString(), "Update", new object{}, new { @class = "button primaryAction" })</div>
<div class="manage">@Html.ActionLink(T("Refresh").ToString(), "Update", new { cameFrom = "Modules" }, new { @class = "button primaryAction" })</div>
@using ( Html.BeginFormAntiForgeryPost(Url.Action("Modules", "Gallery")) ) {
<fieldset class="bulk-actions">
<label for="filterResults" class="bulk-filter">@T("Feed:")</label>
@@ -27,7 +27,7 @@
</div>
<div class="related">
@Html.ActionLink(T("Install").ToString(), "Install", new RouteValueDictionary {{"SyndicationId",item.SyndicationItem.Id}})@T(" | ")
@Html.ActionLink(T("Install").ToString(), "Install", new RouteValueDictionary {{"SyndicationId",item.SyndicationItem.Id},{"cameFrom", "Modules"}})@T(" | ")
<a href="@item.PackageStreamUri">@T("Download")</a>
</div>
@@ -40,5 +40,4 @@
</div>
</li>}
</ul>
}
}

View File

@@ -0,0 +1,49 @@
@model Orchard.Packaging.ViewModels.PackagingModulesViewModel
@{
Style.Require("PackagingAdmin");
Style.Require("ThemesAdmin");
}
<h1>@Html.TitleForPage(T("Browse Gallery - Themes").ToString())</h1>
<div class="manage">@Html.ActionLink(T("Refresh").ToString(), "Update", new { cameFrom = "Themes" }, new { @class = "button primaryAction" })</div>
@using ( Html.BeginFormAntiForgeryPost(Url.Action("Themes", "Gallery")) ) {
<fieldset class="bulk-actions">
<label for="filterResults" class="bulk-filter">@T("Feed:")</label>
<select id="sourceId" name="sourceId">
@Html.SelectOption("", Model.SelectedSource == null, T("Any (show all feeds)").ToString())
@foreach (var source in Model.Sources) {
Html.SelectOption(source.Id, Model.SelectedSource != null && Model.SelectedSource.Id == source.Id, source.FeedTitle);
}
</select>
<button type="submit">@T("Apply")</button>
</fieldset>
}
@if (Model.Modules.Count() > 0) {
<ul class="templates">
@foreach (var item in Model.Modules) {
<li>
@{
var author = item.SyndicationItem.Authors.Any() ? String.Join(", ", item.SyndicationItem.Authors.Select(a => a.Name)) : T("Unknown").Text;
var title = item.SyndicationItem.Title == null ? T("(No title)").Text : item.SyndicationItem.Title.Text;
var thumbnail = item.SyndicationItem.Links.Where(l=>l.RelationshipType=="thumbnail").Select(l=>l.Uri.ToString()).FirstOrDefault();
}
<div>
<h3>@title</h3>
@if(!String.IsNullOrEmpty(thumbnail)) {
@Html.Image(thumbnail, Html.Encode(title), null)
}
<br/>
@Html.ActionLink(T("Install").ToString(), "Install", new RouteValueDictionary {{"SyndicationId",item.SyndicationItem.Id},{"cameFrom", "Themes" }}, new Dictionary<string, object> { { "class", "button" } })
<a class="button" href="@item.PackageStreamUri">@T("Download")</a>
<h5>@T("By") @author</h5>
<p>
@T("Version: {0}", "1.0")<br />
@(item.SyndicationItem.Summary == null ? T("(No description").Text : item.SyndicationItem.Summary.Text)<br />
</p>
</div>
</li>
}
</ul>
}

View File

@@ -0,0 +1,9 @@
using JetBrains.Annotations;
using Orchard.ContentManagement.Drivers;
using Orchard.Widgets.Models;
namespace Orchard.Widgets.Drivers {
[UsedImplicitly]
public class LayerPartDriver : ContentPartDriver<LayerPart> {
}
}

View File

@@ -0,0 +1,9 @@
using JetBrains.Annotations;
using Orchard.ContentManagement.Drivers;
using Orchard.Widgets.Models;
namespace Orchard.Widgets.Drivers {
[UsedImplicitly]
public class WidgetPartDriver : ContentPartDriver<WidgetPart> {
}
}

View File

@@ -23,9 +23,9 @@ namespace Orchard.Widgets {
public void CreateDefaultLayers() {
IContent defaultLayer = _contentManager.Create<LayerPart>("Layer", t => { t.Record.Name = "Default"; t.Record.LayerRule = "true"; });
_contentManager.Publish(defaultLayer.ContentItem);
IContent authenticatedLayer = _contentManager.Create<LayerPart>("Layer", t => { t.Record.Name = "Authenticated"; t.Record.LayerRule = "Authenticated"; });
IContent authenticatedLayer = _contentManager.Create<LayerPart>("Layer", t => { t.Record.Name = "Authenticated"; t.Record.LayerRule = "authenticated"; });
_contentManager.Publish(authenticatedLayer.ContentItem);
IContent anonymousLayer = _contentManager.Create<LayerPart>("Layer", t => { t.Record.Name = "Anonymous"; t.Record.LayerRule = "not Authenticated"; });
IContent anonymousLayer = _contentManager.Create<LayerPart>("Layer", t => { t.Record.Name = "Anonymous"; t.Record.LayerRule = "not authenticated"; });
_contentManager.Publish(anonymousLayer.ContentItem);
}
}
@@ -65,6 +65,7 @@ namespace Orchard.Widgets {
cfg => cfg
.WithPart("WidgetPart")
.WithPart("BodyPart")
.WithSetting("stereotype", "widget")
);
CreateDefaultLayers();

View File

@@ -59,6 +59,8 @@
<ItemGroup>
<Compile Include="AdminMenu.cs" />
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Drivers\LayerPartDriver.cs" />
<Compile Include="Drivers\WidgetPartDriver.cs" />
<Compile Include="Migrations.cs" />
<Compile Include="Handlers\LayerPartHandler.cs" />
<Compile Include="Handlers\WidgetPartHandler.cs" />

View File

@@ -11,7 +11,7 @@ namespace Orchard.Widgets.RuleEngine {
}
public void Process(RuleContext ruleContext) {
if (!String.Equals(ruleContext.FunctionName, "Authenticated", StringComparison.OrdinalIgnoreCase)) {
if (!String.Equals(ruleContext.FunctionName, "authenticated", StringComparison.OrdinalIgnoreCase)) {
return;
}

View File

@@ -10,7 +10,7 @@ namespace Orchard.Widgets.RuleEngine {
}
public void Process(RuleContext ruleContext) {
if (!String.Equals(ruleContext.FunctionName, "Url", StringComparison.OrdinalIgnoreCase)) {
if (!String.Equals(ruleContext.FunctionName, "url", StringComparison.OrdinalIgnoreCase)) {
return;
}

View File

@@ -111,8 +111,10 @@
<Content Include="Themes\TheAdmin\Styles\images\menuOpen.gif" />
<Content Include="Themes\TheAdmin\Styles\images\menuOpenHover.gif" />
<Content Include="Themes\TheThemeMachine\draft.html" />
<Content Include="Themes\TheThemeMachine\Styles\site.css" />
<Content Include="Themes\TheThemeMachine\Theme.png" />
<Content Include="Themes\TheThemeMachine\Theme.txt" />
<None Include="Themes\TheThemeMachine\Views\Document.cshtml" />
<Content Include="Web.config">
<SubType>Designer</SubType>
</Content>
@@ -285,17 +287,16 @@
<Content Include="Themes\TheAdmin\Views\User.cshtml" />
<Content Include="Themes\TheAdmin\Views\Header.cshtml" />
<Content Include="Themes\Web.config" />
<Content Include="Themes\TheThemeMachine\Views\Layout.cshtml" />
<Content Include="Themes\TheThemeMachine\Views\Zone.cshtml" />
<Content Include="Themes\TheThemeMachine\Views\Zone-Sidebar.cshtml" />
<Content Include="Themes\TheThemeMachine\Views\Zone-Navigation.cshtml" />
<Content Include="Themes\TheThemeMachine\Views\Menu.cshtml" />
<Content Include="Themes\TheThemeMachine\Views\Items\Content.Blog.cshtml" />
<None Include="Themes\TheThemeMachine\Views\Layout.cshtml" />
<None Include="Themes\TheThemeMachine\Views\Menu.cshtml">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />
<Folder Include="Themes\ClassicDark\DesignerNotes\" />
<Folder Include="Themes\SafeMode\Content\Images\" />
<Folder Include="Themes\TheThemeMachine\Styles\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

View File

@@ -0,0 +1,155 @@
/* Reset
***************************************************************/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
font-family: inherit;
vertical-align: baseline;
}
/* remember to define focus styles! */
:focus {
outline: 0;
}
body {
line-height: 1;
color: black;
background: white;
}
ol, ul {
list-style: none;
}
/* tables still need 'cellspacing="0"' in the markup */
table {
border-collapse: separate;
border-spacing: 0;
}
caption, th, td {
text-align: left;
font-weight: normal;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: "";
}
blockquote, q {
quotes: "" "";
}
/* Tell the browser to render HTML 5 elements as block */
header, footer, aside, nav, article {
display: block;
}
/* Clearing Float
***************************************************************/
group:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.group {display: inline-block;} /* for IE/Mac */
/* Typography (Optional)
***************************************************************/
/* General
***************************************************************/
/* Default font settings.
The font-size 62.5% sets the base font to 10px */
body {
font-size: 62.5%;
color: #333;
background: #fff;
font-family: Segoe UI,Trebuchet,Arial,Sans-Serif;
}
a {}
a:link {}
a:hover{}
a:visited{}
/* Headings */
h1,h2,h3,h4,h5,h6 { font-weight: normal; }
h1 { font-size: 3em;}
h2 { font-size: 1.3em; }
h3 { font-size: 1.2em; }
h4 { font-size: 1.1em; }
h5 { font-size: 1em; }
h6 { font-size: 1em; }
h1 img, h2 img, h3 img,
h4 img, h5 img, h6 img {
margin: 0;
}
p {
font-size:1.2em;
line-height:2em;
}
/* Structure
***************************************************************/
#layout-wrapper {
width:960px;
margin:0 auto;
}
#header {}
#logo {}
/* Navigation */
nav ul li {
margin:2em 0 0 0;
float:left;
}
nav ul li a {
font-size:1.4em;
margin:0 1.8em;
display:block;
text-decoration:none;
text-transform:uppercase;
float:left;
}
#footer {}
/* Main
***************************************************************/
/* Secondary
***************************************************************/
/* Forms
***************************************************************/
/* Misc
***************************************************************/
/* For testing purposes */
div, nav, section {
border:1px solid #CCC;
}

View File

@@ -0,0 +1,19 @@
@using Orchard.Mvc.Html
@using Orchard.UI.Resources
@{
RegisterLink(new LinkEntry {Type = "image/x-icon", Rel = "shortcut icon", Href = Url.Content("~/modules/orchard.themes/Content/orchard.ico")});
}
<!DOCTYPE html>
<html lang="en" class="static @Html.ClassForPage()">
<head>
<meta charset="utf-8" />
<title>@Model.Title</title>
@Display(Model.Head)
<script>(function(d){d.className="dyn"+d.className.substring(6,d.className.length);})(document.documentElement);</script>
</head>
<body>
@// Layout (template) is in the Body zone @ the default position (nothing, zero, zilch)
@Display(Model.Body)
@Display(Model.Tail)
</body>
</html>

View File

@@ -0,0 +1,10 @@
@using Orchard.Blogs.Extensions
@using Orchard.UI.Resources
@{
RegisterLink(new LinkEntry { Rel = "wlwmanifest", Type = "application/wlwmanifest+xml", Href = Url.BlogLiveWriterManifest((string)Model.Slug) });
RegisterLink(new LinkEntry { Rel = "EditURI", Type = "application/rsd+xml", Title = "RSD", Href = Url.BlogRsd((string)Model.Slug) });
}
<h1>@Html.TitleForPage((string)Model.Title)</h1>
@Display(Model.manage)
@Display(Model.metadata)
@Display(Model.primary)

View File

@@ -1,34 +1,55 @@
@using Orchard.UI.Resources
@{
Style.Include("~/themes/Classic/styles/site.css");
Style.Include("~/themes/Classic/styles/blog.css");
}
<div id="wrapper">
@// HTML.Include will render a div with a class="user-display"
@// Can use this -> {Html.Include("User");}
@// or the following. At least they appear to do the same thing currently. The first is a standard Html.Include, the second "displays the (New) User shape"
@Display.User()
@// Top Navigation and branding
<div id="headercontainer">
<div id="header">
<h1>@WorkContext.CurrentSite.SiteName</h1>
<div class="menucontainer">
@Display(Model.Navigation)
</div>
<div class="clearBoth"></div>
</div>
</div>
@{
Style.Include("site.css");
<div id="main">
<div id="content">
@// Main Content
@Display(Model.Content)
// cool stuff goes up here
var homeUrl = Href("~/");
// Zone is an alias for Display
Func<dynamic, dynamic> Zone = x => Display(x);
if (Model.Sidebar != null) {
Html.AddPageClassNames(new[]{"icanhassidebar"});
}
}
<div id="layout-wrapper">
<header id="layout-header">
@// needs to be the page title, not page (head) title...
<h1><a href="@homeUrl">@WorkContext.CurrentSite.SiteName</a></h1>
@if(Model.Header != null) {
<div id="header">
@Zone(Model.Header)
</div>
<div id="sidebar">
@Display(Model.search)
@Display(Model.sidebar)
}
@if(Model.Navigation != null) {
<div id="navigation">
@Zone(Model.Navigation)
</div>
@// End Content
@Display.Footer(Navigation:Model.Navigation)
}
</header>
@if(Model.Messages != null) {
<div id="messages">
@Zone(Model.Messages)
</div>
</div>
}
@if(Model.Featured != null) {
<div id="featured">
@Zone(Model.Featured)
</div>
}
@// the model content for the page is in the Content zone @ the default position (nothing, zero, zilch)
@if(Model.Content != null) {
<div id="content">
@Zone(Model.Content)
</div>
}
@if(Model.Sidebar != null) {
<aside>
@Zone(Model.Sidebar)
</aside>
}
@if(Model.Footer != null) {
<footer>
@Zone(Model.Footer)
</footer>
}
</div>

View File

@@ -1,13 +1,13 @@
<!-- Model is Model.Menu from the layout (Page.Menu) -->
<nav>
<ul>
<li class="first current"><a href="#">Home</a></li>
<li><a href="#">Blog</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Full Page</a></li>
<li><a href="#">Image Page</a></li>
<li><a href="#">Gallery Page</a></li>
<li><a href="#">Nested Page</a></li>
<li class="last"><a href="#">Contact</a></li>
</ul>
@{
// these should move somewhere else
Model.Id = "menu-" + Model.MenuName.ToLower();
Model.Classes.Add(Model.Id);
Model.Classes.Add("menu");
var tag = Html.Resolve<Orchard.DisplayManagement.Shapes.ITagBuilderFactory>().Create(Model, "ul");
}
@tag.StartElement
@DisplayChildren(Model)
@tag.EndElement <!-- /@Model.Id -->
</nav>

View File

@@ -1,3 +0,0 @@
<div class="zone zone-@Model.ZoneName">
@Display...
</div>

View File

@@ -1,3 +0,0 @@
<div class="zone zone-@Model.ZoneName">
@Display...
</div>

View File

@@ -1,4 +0,0 @@

<div class="zone zone-@Model.ZoneName">
@Display...
</div>

View File

@@ -8,6 +8,7 @@ namespace Orchard.FileSystems.WebSite {
/// </summary>
public interface IWebSiteFolder : IVolatileProvider {
IEnumerable<string> ListDirectories(string virtualPath);
IEnumerable<string> ListFiles(string virtualPath, bool recursive);
bool FileExists(string virtualPath);
string ReadFile(string virtualPath);

View File

@@ -4,7 +4,6 @@ using System.IO;
using System.Linq;
using System.Web.Hosting;
using Orchard.Caching;
using Orchard.Environment;
using Orchard.FileSystems.VirtualPath;
namespace Orchard.FileSystems.WebSite {
@@ -18,18 +17,26 @@ namespace Orchard.FileSystems.WebSite {
}
public IEnumerable<string> ListDirectories(string virtualPath) {
if (!HostingEnvironment.VirtualPathProvider.DirectoryExists(virtualPath))
if (!_virtualPathProvider.DirectoryExists(virtualPath)) {
return Enumerable.Empty<string>();
}
return HostingEnvironment.VirtualPathProvider
.GetDirectory(virtualPath)
.Directories.OfType<VirtualDirectory>()
.Select(d => d.VirtualPath)
.ToArray();
return _virtualPathProvider.ListDirectories(virtualPath);
}
private IEnumerable<string> ListFiles(IEnumerable<string> directories) {
return directories.SelectMany(d => ListFiles(d, true));
}
public IEnumerable<string> ListFiles(string virtualPath, bool recursive) {
if (!recursive) {
return _virtualPathProvider.ListFiles(virtualPath);
}
return _virtualPathProvider.ListFiles(virtualPath).Concat(ListFiles(ListDirectories(virtualPath)));
}
public bool FileExists(string virtualPath) {
return HostingEnvironment.VirtualPathProvider.FileExists(virtualPath);
return _virtualPathProvider.FileExists(virtualPath);
}
public string ReadFile(string virtualPath) {
@@ -37,8 +44,9 @@ namespace Orchard.FileSystems.WebSite {
}
public string ReadFile(string virtualPath, bool actualContent) {
if (!HostingEnvironment.VirtualPathProvider.FileExists(virtualPath))
if (!_virtualPathProvider.FileExists(virtualPath)) {
return null;
}
if (actualContent) {
var physicalPath = _virtualPathProvider.MapPath(virtualPath);
@@ -49,7 +57,7 @@ namespace Orchard.FileSystems.WebSite {
}
}
else {
using (var stream = VirtualPathProvider.OpenFile(Normalize(virtualPath))) {
using (var stream = _virtualPathProvider.OpenFile(Normalize(virtualPath))) {
using (var reader = new StreamReader(stream)) {
return reader.ReadToEnd();
}
@@ -74,7 +82,7 @@ namespace Orchard.FileSystems.WebSite {
}
}
else {
using (var stream = VirtualPathProvider.OpenFile(Normalize(virtualPath))) {
using (var stream = _virtualPathProvider.OpenFile(Normalize(virtualPath))) {
stream.CopyTo(destination);
}
}
@@ -85,6 +93,8 @@ namespace Orchard.FileSystems.WebSite {
}
static string Normalize(string virtualPath) {
// todo: use IVirtualPathProvider instance instead of static.
// Currently IVirtualPathProvider has no way of doing normalization like this
return HostingEnvironment.VirtualPathProvider.GetFile(virtualPath).VirtualPath;
}
}

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 + ":" + contentType);
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

@@ -7,7 +7,7 @@
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{8A4E42CE-79F8-4BE2-8B1E-A6B83432123B}</ProjectGuid>
<ProjectTypeGuids>{e53f8fea-eae0-44a6-8774-ffd645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>PackageIndexReferenceImplementation</RootNamespace>

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)'^'));