Hooked up everything for blog archives. Currently no UI to point to it though. Not sure how we're going to do that without widgets. Maybe with a hardcoded action filter for now?

--HG--
extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4045086
This commit is contained in:
ErikPorter
2010-01-07 01:27:09 +00:00
parent 4d7faf669b
commit 6d9f911a9e
13 changed files with 238 additions and 12 deletions

View File

@@ -7,7 +7,6 @@ using Orchard.Blogs.ViewModels;
using Orchard.Data;
using Orchard.Localization;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.Mvc.Results;
using Orchard.Security;
using Orchard.UI.Notify;

View File

@@ -66,7 +66,7 @@ namespace Orchard.Blogs.Controllers {
return Combined(
ContentItemTemplate("Items/Blogs.Blog").LongestMatch(displayType, "Summary", "DetailAdmin", "SummaryAdmin"),
blogPosts == null ? null : ContentPartTemplate(blogPosts, "Parts/Blogs.BlogPost.List", "").Location("body"));
blogPosts == null ? null : ContentPartTemplate(blogPosts, "Parts/Blogs.BlogPost.List", "").Location("primary"));
}
protected override DriverResult Editor(Blog blog) {

View File

@@ -1,3 +1,4 @@
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using Orchard.Blogs.Extensions;
@@ -46,6 +47,7 @@ namespace Orchard.Blogs.Controllers {
if (!_authorizer.Authorize(Permissions.ViewPost, T("Couldn't view blog post")))
return new HttpUnauthorizedResult();
//TODO: (erikpo) Move looking up the current blog up into a modelbinder
Blog blog = _blogService.Get(blogSlug);
if (blog == null)
@@ -64,9 +66,27 @@ namespace Orchard.Blogs.Controllers {
return View(model);
}
public ActionResult ListByArchive(string blogSlug, string archiveData) {
//TODO: (erikpo) Move looking up the current blog up into a modelbinder
Blog blog = _blogService.Get(blogSlug);
if (blog == null)
return new NotFoundResult();
var archive = new ArchiveData(archiveData);
var model = new BlogPostArchiveViewModel {
Blog = blog,
ArchiveData = archive,
BlogPosts = _blogPostService.Get(blog, archive).Select(b => _contentManager.BuildDisplayModel(b, "Summary"))
};
return View(model);
}
public ActionResult Slugify(string value) {
string slug = value;
//TODO: (erikpo) Move this into a utility class
if (!string.IsNullOrEmpty(value)) {
Regex regex = new Regex("([^a-z0-9-_]?)", RegexOptions.IgnoreCase | RegexOptions.Compiled);

View File

@@ -14,6 +14,18 @@ namespace Orchard.Blogs.Extensions {
return urlHelper.Action("Item", "Blog", new {blogSlug, area = "Orchard.Blogs"});
}
public static string BlogArchiveYear(this UrlHelper urlHelper, string blogSlug, int year) {
return urlHelper.Action("ListByArchive", "BlogPost", new { blogSlug, archiveData = year.ToString(), area = "Orchard.Blogs" });
}
public static string BlogArchiveMonth(this UrlHelper urlHelper, string blogSlug, int year, int month) {
return urlHelper.Action("ListByArchive", "BlogPost", new { blogSlug, archiveData = string.Format("{0}/{1}", year, month), area = "Orchard.Blogs" });
}
public static string BlogArchiveDay(this UrlHelper urlHelper, string blogSlug, int year, int month, int day) {
return urlHelper.Action("ListByArchive", "BlogPost", new {blogSlug, archiveData = string.Format("{0}/{1}/{2}", year, month, day), area = "Orchard.Blogs"});
}
public static string BlogForAdmin(this UrlHelper urlHelper, string blogSlug) {
return urlHelper.Action("Item", "BlogAdmin", new {blogSlug, area = "Orchard.Blogs"});
}

View File

@@ -0,0 +1,125 @@
using System;
using System.Text;
using System.Text.RegularExpressions;
namespace Orchard.Blogs.Models {
public class ArchiveData : IEquatable<ArchiveData>, IComparable<ArchiveData> {
private static readonly string _defaultString = DateTime.Now.Year.ToString();
private static readonly Regex archiveDataRegex =
new Regex(@"^(?<year>\d{4})(?:/(?<month>\d{1,2})?(?:/(?<day>\d{1,2})?)?)?(?:/(?:page(?<page>\d+))?)?$",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
public ArchiveData(string rawData) {
if (!string.IsNullOrEmpty(rawData)) {
Match archiveDataMatch = archiveDataRegex.Match(rawData);
int year;
if (archiveDataMatch.Groups["year"].Success &&
int.TryParse(archiveDataMatch.Groups["year"].Value, out year)) {
Year = year;
}
int month;
if (archiveDataMatch.Groups["month"].Success &&
int.TryParse(archiveDataMatch.Groups["month"].Value, out month)) {
Month = month;
}
int day;
if (archiveDataMatch.Groups["day"].Success &&
int.TryParse(archiveDataMatch.Groups["day"].Value, out day)) {
Day = day;
}
int page;
if (archiveDataMatch.Groups["page"].Success &&
int.TryParse(archiveDataMatch.Groups["page"].Value, out page)) {
Page = page;
}
else {
Page = 1;
}
}
}
public int Page { get; private set; }
public int Year { get; private set; }
public int Month { get; private set; }
public int Day { get; private set; }
public static string DefaultString {
get { return _defaultString; }
}
#region IComparable<ArchiveData> Members
public int CompareTo(ArchiveData other) {
return ToDateTime().CompareTo(other.ToDateTime());
}
#endregion
#region IEquatable<ArchiveData> Members
public bool Equals(ArchiveData other) {
if (other != null) {
return Day == other.Day && Month == other.Month && Page == other.Page && Year == other.Year;
}
return false;
}
#endregion
public override string ToString() {
var sb = new StringBuilder();
if (Year > 0) {
sb.AppendFormat("{0}/", Year);
}
if (Month > 0) {
sb.AppendFormat("{0}/", Month);
}
if (Day > 0) {
sb.AppendFormat("{0}/", Day);
}
if (Page > 1) {
sb.AppendFormat("page{0}/", Page);
}
return sb.Remove(sb.Length - 1, 1).ToString();
}
public DateTime ToDateTime() {
int projectedYear = DateTime.MinValue.Year, projectedMonth = 1, projectedDay = 1;
if (Year > 0) {
projectedYear = Year;
}
if (Month > 0) {
projectedMonth = Month;
}
if (Day > 0) {
projectedDay = Day;
}
return new DateTime(projectedYear, projectedMonth, projectedDay);
}
public override bool Equals(object obj) {
if (obj is ArchiveData) {
return Equals(obj as ArchiveData);
}
return base.Equals(obj);
}
public override int GetHashCode() {
return ToDateTime().GetHashCode();
}
}
}

View File

@@ -81,7 +81,9 @@
<Compile Include="Extensions\HtmlHelperExtensions.cs" />
<Compile Include="Extensions\UriExtensions.cs" />
<Compile Include="Extensions\UrlHelperExtensions.cs" />
<Compile Include="Models\ArchiveData.cs" />
<Compile Include="Permissions.cs" />
<Compile Include="Routing\IsArchiveConstraint.cs" />
<Compile Include="Routing\IsBlogConstraint.cs" />
<Compile Include="Services\BlogService.cs" />
<Compile Include="Controllers\BlogController.cs" />
@@ -97,6 +99,7 @@
<Compile Include="Services\IBlogPostService.cs" />
<Compile Include="Services\IBlogService.cs" />
<Compile Include="ViewModels\AdminBlogsViewModel.cs" />
<Compile Include="ViewModels\BlogPostArchiveViewModel.cs" />
<Compile Include="ViewModels\BlogViewModel.cs" />
<Compile Include="ViewModels\BlogPostViewModel.cs" />
<Compile Include="ViewModels\BlogPostEditViewModel.cs" />
@@ -110,6 +113,7 @@
<Content Include="Package.txt" />
<Content Include="Views\BlogPost\Create.ascx" />
<Content Include="Views\BlogPost\Edit.ascx" />
<Content Include="Views\BlogPost\ListByArchive.ascx" />
<Content Include="Views\DisplayTemplates\Items\Blogs.Blog.DetailAdmin.ascx" />
<Content Include="Views\BlogAdmin\Item.ascx" />
<Content Include="Views\DisplayTemplates\Items\Blogs.Blog.SummaryAdmin.ascx" />

View File

@@ -189,6 +189,23 @@ namespace Orchard.Blogs {
},
new MvcRouteHandler())
},
new RouteDescriptor {
Route = new Route(
"{blogSlug}/Archive/{*archiveData}",
new RouteValueDictionary {
{"area", "Orchard.Blogs"},
{"controller", "BlogPost"},
{"action", "ListByArchive"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_containerProvider)},
{"archiveData", new IsArchiveConstraint()}
},
new RouteValueDictionary {
{"area", "Orchard.Blogs"}
},
new MvcRouteHandler())
},
new RouteDescriptor {
Route = new Route(
"{blogSlug}/{postSlug}",

View File

@@ -0,0 +1,12 @@
using System.Web;
using System.Web.Routing;
using Orchard.Blogs.Models;
namespace Orchard.Blogs.Routing {
public class IsArchiveConstraint : IRouteConstraint {
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values,
RouteDirection routeDirection) {
return values[parameterName] != null && (new ArchiveData(values[parameterName].ToString())).Year > 0;
}
}
}

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.Blogs.Models;
@@ -16,21 +17,37 @@ namespace Orchard.Blogs.Services {
}
public BlogPost Get(Blog blog, string slug) {
return _contentManager.Query<BlogPost, BlogPostRecord >()
.Join<RoutableRecord>().Where(rr => rr.Slug == slug)
.Join<CommonRecord>().Where(cr => cr.Container == blog.Record.ContentItemRecord)
.List().FirstOrDefault();
return
_contentManager.Query<BlogPost, BlogPostRecord>().Join<RoutableRecord>().Where(rr => rr.Slug == slug).
Join<CommonRecord>().Where(cr => cr.Container == blog.Record.ContentItemRecord).List().
SingleOrDefault();
}
public IEnumerable<BlogPost> Get(Blog blog) {
return _contentManager.Query<BlogPost, BlogPostRecord>()
.Join<CommonRecord>().Where(cr => cr.Container == blog.Record.ContentItemRecord)
.OrderByDescending(cr => cr.CreatedUtc)
.List();
return GetBlogQuery(blog).List();
}
public IEnumerable<BlogPost> Get(Blog blog, ArchiveData archiveData) {
var query = GetBlogQuery(blog);
if (archiveData.Day > 0)
query = query.Where(cr => cr.CreatedUtc >= new DateTime(archiveData.Year, archiveData.Month, archiveData.Day) && cr.CreatedUtc < new DateTime(archiveData.Year, archiveData.Month, archiveData.Day + 1));
else if (archiveData.Month > 0)
query = query.Where(cr => cr.CreatedUtc >= new DateTime(archiveData.Year, archiveData.Month, 1) && cr.CreatedUtc < new DateTime(archiveData.Year, archiveData.Month + 1, 1));
else
query = query.Where(cr => cr.CreatedUtc >= new DateTime(archiveData.Year, 1, 1) && cr.CreatedUtc < new DateTime(archiveData.Year + 1, 1, 1));
return query.List();
}
public void Delete(BlogPost blogPost) {
_blogPostRepository.Delete(blogPost.Record);
}
private IContentQuery<BlogPost, CommonRecord> GetBlogQuery(Blog blog) {
return
_contentManager.Query<BlogPost, BlogPostRecord>().Join<CommonRecord>().Where(
cr => cr.Container == blog.Record.ContentItemRecord).OrderByDescending(cr => cr.CreatedUtc);
}
}
}

View File

@@ -5,6 +5,7 @@ namespace Orchard.Blogs.Services {
public interface IBlogPostService : IDependency {
BlogPost Get(Blog blog, string slug);
IEnumerable<BlogPost> Get(Blog blog);
IEnumerable<BlogPost> Get(Blog blog, ArchiveData archiveData);
void Delete(BlogPost blogPost);
}
}

View File

@@ -0,0 +1,11 @@
using System.Collections.Generic;
using Orchard.Blogs.Models;
using Orchard.Mvc.ViewModels;
namespace Orchard.Blogs.ViewModels {
public class BlogPostArchiveViewModel : BaseViewModel {
public Blog Blog { get; set; }
public ArchiveData ArchiveData { get; set; }
public IEnumerable<ContentItemViewModel<BlogPost>> BlogPosts { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<BlogPostArchiveViewModel>" %>
<%@ Import Namespace="Orchard.Blogs.Extensions"%>
<%@ Import Namespace="Orchard.Blogs.ViewModels"%>
<h1><%=Html.TitleForPage(T("Archives").ToString(), Model.ArchiveData.Year.ToString(), Model.ArchiveData.Month > 0 ? new DateTime(Model.ArchiveData.Year, Model.ArchiveData.Month, 1).ToString("MMMM") : null, Model.ArchiveData.Day > 0 ? Model.ArchiveData.Day.ToString() : null)%></h1>
<%=T("Archives").ToString()
%> / <%=Html.Link(Model.ArchiveData.Year.ToString(), Url.BlogArchiveYear(Model.Blog.Slug, Model.ArchiveData.Year))
%><%=Model.ArchiveData.Month > 0 ? string.Format(" / {0}", Html.Link(Model.ArchiveData.ToDateTime().ToString("MMMM"), Url.BlogArchiveMonth(Model.Blog.Slug, Model.ArchiveData.Year, Model.ArchiveData.Month))) : ""
%><%=Model.ArchiveData.Day > 0 ? string.Format(" / {0}", Html.Link(Model.ArchiveData.Day.ToString(), Url.BlogArchiveDay(Model.Blog.Slug, Model.ArchiveData.Year, Model.ArchiveData.Month, Model.ArchiveData.Day))) : ""
%>
<%=Html.UnorderedList(Model.BlogPosts, (c, i) => Html.DisplayForItem(c).ToHtmlString(), "blogPosts contentItems")%>

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using Orchard.Extensions;
using Orchard.Mvc.Html;
using Orchard.Themes;