Hooking up create BlogPost and some other service changes to make sure getting posts is scoped to Blog.

--HG--
extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4042128
This commit is contained in:
ErikPorter
2009-11-25 01:34:23 +00:00
parent 8bd6e8acf4
commit 24656896da
17 changed files with 194 additions and 29 deletions

View File

@@ -4,6 +4,7 @@ using Orchard.Blogs.Extensions;
using Orchard.Blogs.Models;
using Orchard.Blogs.Services;
using Orchard.Blogs.ViewModels;
using Orchard.Core.Common.Models;
using Orchard.Data;
using Orchard.Localization;
using Orchard.Models;
@@ -56,13 +57,13 @@ namespace Orchard.Blogs.Controllers {
if (!ModelState.IsValid)
return View(model);
Blog blog = _blogService.CreateBlog(model.ToCreateBlogParams());
Blog blog = _blogService.Create(model.ToCreateBlogParams());
//TEMP: (erikpo) ensure information has committed for this record
var session = _sessionLocator.For(typeof(BlogRecord));
session.Flush();
return Redirect(Url.BlogEdit(model.Slug));
return Redirect(Url.BlogEdit(blog.As<RoutableAspect>().Slug));
}
public ActionResult Edit(string blogSlug) {

View File

@@ -1,14 +1,21 @@
using System.Web.Mvc;
using Orchard.Blogs.Extensions;
using Orchard.Blogs.Models;
using Orchard.Blogs.Services;
using Orchard.Blogs.ViewModels;
using Orchard.Core.Common.Models;
using Orchard.Data;
using Orchard.Models;
using Orchard.Mvc.Results;
namespace Orchard.Blogs.Controllers {
public class BlogPostController : Controller {
private readonly ISessionLocator _sessionLocator;
private readonly IBlogService _blogService;
private readonly IBlogPostService _blogPostService;
public BlogPostController(IBlogService blogService, IBlogPostService blogPostService) {
public BlogPostController(ISessionLocator sessionLocator, IBlogService blogService, IBlogPostService blogPostService) {
_sessionLocator = sessionLocator;
_blogService = blogService;
_blogPostService = blogPostService;
}
@@ -36,5 +43,37 @@ namespace Orchard.Blogs.Controllers {
return View(post);
}
public ActionResult Create(string blogSlug)
{
//TODO: (erikpo) Move looking up the current blog up into a modelbinder
Blog blog = _blogService.Get(blogSlug);
if (blog == null)
return new NotFoundResult();
return View(new CreateBlogPostViewModel() {Blog = blog});
}
[HttpPost]
public ActionResult Create(string blogSlug, CreateBlogPostViewModel model)
{
//TODO: (erikpo) Move looking up the current blog up into a modelbinder
Blog blog = _blogService.Get(blogSlug);
if (blog == null)
return new NotFoundResult();
if (!ModelState.IsValid)
return View(model);
BlogPost blogPost = _blogPostService.Create(model.ToCreateBlogPostParams(blog));
//TEMP: (erikpo) ensure information has committed for this record
var session = _sessionLocator.For(typeof(BlogPostRecord));
session.Flush();
return Redirect(Url.BlogPostEdit(blogSlug, blogPost.As<RoutableAspect>().Slug));
}
}
}

View File

@@ -0,0 +1,11 @@
using Orchard.Blogs.Models;
using Orchard.Blogs.Services;
using Orchard.Blogs.ViewModels;
namespace Orchard.Blogs.Extensions {
public static class BlogPostCreateViewModelExtensions {
public static CreateBlogPostParams ToCreateBlogPostParams(this CreateBlogPostViewModel viewModel, Blog blog) {
return new CreateBlogPostParams() {Blog = blog, Title = viewModel.Title, Body = viewModel.Body, Slug = viewModel.Slug, Published = viewModel.Published};
}
}
}

View File

@@ -15,7 +15,11 @@ namespace Orchard.Blogs.Extensions {
}
public static string BlogPost(this UrlHelper urlHelper, string blogSlug, string postSlug) {
return "#";
return urlHelper.Action("Item", "BlogPost", new {blogSlug, postSlug, area = "Orchard.Blogs"});
}
public static string BlogPostEdit(this UrlHelper urlHelper, string blogSlug, string postSlug) {
return urlHelper.Action("Edit", "BlogPost", new {blogSlug, postSlug, area = "Orchard.Blogs"});
}
}
}

View File

@@ -1,7 +1,9 @@
using System;
using Orchard.Models;
namespace Orchard.Blogs.Models {
public class BlogPost : ContentPart<BlogPostRecord> {
public Blog Blog { get; set; }
public DateTime? Published { get { return Record.Published; } }
}
}

View File

@@ -1,19 +1,9 @@
//using System;
using System;
using Orchard.Models.Records;
using Orchard.Users.Models;
namespace Orchard.Blogs.Models {
public class BlogPostRecord : ContentPartRecord {
public virtual BlogRecord Blog { get; set; }
public virtual UserRecord Creator { get; set; }
public virtual string Title { get; set; }
public virtual string Body { get; set; }
public virtual string BodyShort { get; set; }
//TODO: (erikpo) Probably need some sort of body source type to keep track of what created the text so its available to plugins to use appropriately.
public virtual string Slug { get; set; }
public virtual DateTime? Published { get; set; }
//public virtual DateTime Created { get; set; }
//public virtual DateTime Modified { get; set; }
}
}

View File

@@ -68,6 +68,7 @@
<Compile Include="AdminMenu.cs" />
<Compile Include="Controllers\BlogPostController.cs" />
<Compile Include="Extensions\BlogCreateViewModelExtensions.cs" />
<Compile Include="Extensions\BlogPostCreateViewModelExtensions.cs" />
<Compile Include="Extensions\UrlHelperExtensions.cs" />
<Compile Include="Routing\IsBlogConstraint.cs" />
<Compile Include="Services\BlogService.cs" />
@@ -81,19 +82,25 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Routes.cs" />
<Compile Include="Services\BlogPostService.cs" />
<Compile Include="Services\CreateBlogPostParams.cs" />
<Compile Include="Services\IBlogPostService.cs" />
<Compile Include="Services\CreateBlogParams.cs" />
<Compile Include="Services\IBlogService.cs" />
<Compile Include="ViewModels\BlogsViewModel.cs" />
<Compile Include="ViewModels\BlogViewModel.cs" />
<Compile Include="ViewModels\CreateBlogPostViewModel.cs" />
<Compile Include="ViewModels\CreateBlogViewModel.cs" />
<Compile Include="ViewModels\BlogEditViewModel.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Package.txt" />
<Content Include="Views\BlogPost\Create.aspx" />
<Content Include="Views\Blog\Create.aspx" />
<Content Include="Views\BlogPost\ListByBlog.aspx" />
<Content Include="Views\Blog\Edit.aspx" />
<Content Include="Views\Blog\EditorTemplates\BlogEditViewModel.ascx" />
<Content Include="Views\Blog\EditorTemplates\BlogPermalink.ascx" />
<Content Include="Views\Blog\EditorTemplates\CreateBlogViewModel.ascx" />
<Content Include="Views\Blog\Item.aspx" />
<Content Include="Views\Blog\List.aspx" />
<Content Include="Views\Shared\Foot.aspx" />

View File

@@ -51,6 +51,38 @@ namespace Orchard.Blogs {
},
new MvcRouteHandler())
},
new RouteDescriptor {
Route = new Route(
"Admin/Blogs/{blogSlug}/Posts",
new RouteValueDictionary {
{"area", "Orchard.Blogs"},
{"controller", "BlogPost"},
{"action", "ListForAdmin"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_blogService)}
},
new RouteValueDictionary {
{"area", "Orchard.Blogs"}
},
new MvcRouteHandler())
},
new RouteDescriptor {
Route = new Route(
"Admin/Blogs/{blogSlug}/Posts/Create",
new RouteValueDictionary {
{"area", "Orchard.Blogs"},
{"controller", "BlogPost"},
{"action", "Create"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_blogService)}
},
new RouteValueDictionary {
{"area", "Orchard.Blogs"}
},
new MvcRouteHandler())
},
new RouteDescriptor {
Route = new Route(
"Admin/Blogs",

View File

@@ -1,30 +1,49 @@
using System.Collections.Generic;
using System.Linq;
using Orchard.Blogs.Models;
using Orchard.Core.Common.Models;
using Orchard.Core.Common.Records;
using Orchard.Data;
using Orchard.Models;
namespace Orchard.Blogs.Services {
public class BlogPostService : IBlogPostService {
private readonly IContentManager _contentManager;
private readonly IRepository<BlogPostRecord> _repository;
private readonly IRepository<RoutableRecord> _routableRepository;
public BlogPostService(IContentManager contentManager, IRepository<BlogPostRecord> repository) {
public BlogPostService(IContentManager contentManager, IRepository<RoutableRecord> routableRepository) {
_contentManager = contentManager;
_repository = repository;
_routableRepository = routableRepository;
}
public BlogPost Get(Blog blog, string slug) {
BlogPostRecord record = _repository.Get(bpr => bpr.Blog.Id == blog.Record.Id/* && bpr.Blog.Enabled*/ && bpr.Slug == slug);
RoutableRecord record =
_routableRepository.Get(r => r.ContentItem.ContentType.Name == "blogpost" && r.Slug == slug);
BlogPost blogPost = record != null ? _contentManager.Get<BlogPost>(record.Id) : null;
return _contentManager.Get<BlogPost>(record.Id);
return blogPost != null && blogPost.Blog.ContentItem.Id == blog.ContentItem.Id ? blogPost : null;
}
public IEnumerable<BlogPost> Get(Blog blog) {
//TODO: (erikpo) Sort by published desc
IEnumerable<BlogPostRecord> items =_repository.Fetch(bpr => bpr.Blog.Id == blog.Record.Id/* && bpr.Blog.Enabled, bpr => bpr.Asc(bpr2 => bpr2.Slug)*/);
//TODO: (erikpo) Figure out how to sort by published date
IEnumerable<RoutableRecord> records =
_routableRepository.Fetch(rr => rr.ContentItem.ContentType.Name == "blogpost"
/*, bpr => bpr.Asc(bpr2 => bpr2.Published.GetValueOrDefault(new DateTime(2099, 1, 1)))*/);
return items.Select(br => _contentManager.Get(br.Id).As<BlogPost>());
//TODO: (erikpo) Need to filter by blog in the line above instead of manually here
return
records.Select(r => _contentManager.Get(r.Id).As<BlogPost>()).Where(
bp => bp.Blog.ContentItem.Id == blog.ContentItem.Id);
}
public BlogPost Create(CreateBlogPostParams parameters) {
return _contentManager.Create<BlogPost>("blogpost", bp =>
{
bp.Record.Blog = parameters.Blog.Record;
bp.Record.Published = parameters.Published;
bp.As<RoutableAspect>().Record.Title = parameters.Title;
bp.As<RoutableAspect>().Record.Slug = parameters.Slug;
});
}
}
}

View File

@@ -9,12 +9,10 @@ using Orchard.Models;
namespace Orchard.Blogs.Services {
public class BlogService : IBlogService {
private readonly IContentManager _contentManager;
private readonly IRepository<BlogRecord> _repository;
private readonly IRepository<RoutableRecord> _routableRepository;
public BlogService(IContentManager contentManager, IRepository<BlogRecord> repository, IRepository<RoutableRecord> routableRepository) {
public BlogService(IContentManager contentManager, IRepository<RoutableRecord> routableRepository) {
_contentManager = contentManager;
_repository = repository;
_routableRepository = routableRepository;
}
@@ -30,7 +28,7 @@ namespace Orchard.Blogs.Services {
return records.Select(rr => _contentManager.Get<Blog>(rr.Id));
}
public Blog CreateBlog(CreateBlogParams parameters) {
public Blog Create(CreateBlogParams parameters) {
return _contentManager.Create<Blog>("blog", init => {
init.Record.Description = parameters.Description;
init.As<RoutableAspect>().Record.Title = parameters.Name;

View File

@@ -0,0 +1,12 @@
using System;
using Orchard.Blogs.Models;
namespace Orchard.Blogs.Services {
public class CreateBlogPostParams {
public Blog Blog { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public string Slug { get; set; }
public DateTime? Published { get; set; }
}
}

View File

@@ -5,5 +5,6 @@ namespace Orchard.Blogs.Services {
public interface IBlogPostService : IDependency {
BlogPost Get(Blog blog, string slug);
IEnumerable<BlogPost> Get(Blog blog);
BlogPost Create(CreateBlogPostParams parameters);
}
}

View File

@@ -5,6 +5,6 @@ namespace Orchard.Blogs.Services {
public interface IBlogService : IDependency {
Blog Get(string slug);
IEnumerable<Blog> Get();
Blog CreateBlog(CreateBlogParams parameters);
Blog Create(CreateBlogParams parameters);
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.ComponentModel.DataAnnotations;
using Orchard.Blogs.Models;
using Orchard.Mvc.ViewModels;
namespace Orchard.Blogs.ViewModels {
public class CreateBlogPostViewModel : AdminViewModel {
public Blog Blog { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string Body { get; set; }
//TODO: (erikpo) Need a data type for slug
[Required]
public string Slug { get; set; }
public DateTime? Published { get; set; }
}
}

View File

@@ -1,10 +1,10 @@
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<Orchard.Blogs.ViewModels.CreateBlogViewModel>" %>
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<Orchard.Blogs.ViewModels.CreateBlogViewModel>" ValidateRequest="false" %>
<%@ Import Namespace="Orchard.Blogs.Extensions"%>
<%@ Import Namespace="Orchard.Security" %>
<%@ Import Namespace="Orchard.Mvc.Html" %>
<% Html.Include("Head"); %>
<h2>Create New Blog</h2>
<p><a href="<%=Url.Blogs() %>">Manage Blogs</a> > Create</p>
<p><a href="<%=Url.Blogs() %>">Manage Blogs</a> > Create Blog</p>
<%using (Html.BeginForm()) { %>
<%= Html.ValidationSummary() %>
<%= Html.EditorForModel() %>

View File

@@ -7,6 +7,7 @@
<%=Html.EditorFor(m => m.Slug, "BlogPermalink") %>
</fieldset>
<label for="">Description</label>
<%-- todo: (heskew) shouldn't be TinyMCE'd --%>
<%=Html.TextAreaFor(m => m.Description) %>
<fieldset>
</fieldset>

View File

@@ -0,0 +1,26 @@
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<CreateBlogPostViewModel>" %>
<%@ Import Namespace="Orchard.Blogs.ViewModels"%>
<%@ Import Namespace="Orchard.Blogs.Extensions"%>
<%@ Import Namespace="Orchard.Security" %>
<%@ Import Namespace="Orchard.Mvc.Html" %>
<% Html.Include("Head"); %>
<div class="yui-u">
<h2 class="separator">
Create a New Blog Post</h2>
<p class="bottomSpacer">
<a href="<%=Url.Blogs() %>">Manage Blogs</a> > <a href="<%=Url.BlogEdit(Model.Blog.Slug) %>"><%=Html.Encode(Model.Blog.Name) %></a> > Create Blog Post
</p>
</div>
<div class="yui-u">
<%using (Html.BeginForm()) { %>
<ol>
<%= Html.ValidationSummary() %>
<%= Html.EditorForModel() %>
<li class="clearLayout">
<input class="button" type="submit" value="Create" />
<a href="<%=Url.Blogs() %>" class="button">Cancel</a>
</li>
</ol>
<%}/*EndForm*/%>
</div>
<% Html.Include("Foot"); %>