mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-11-28 17:32:44 +08:00
- Changing all BlogPost admin actions to use the post's id instead of slug (since only published slugs are guaranteed to be unique in any container)
- Changing the BlogPost publish action to POST only - Changing how BlogPosts are published on create to get the publishing/published events fired (temp workaround) - Adding unique slug generation on publish for out of the editor for a unique published slug guarantee --HG-- extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4045793
This commit is contained in:
@@ -39,7 +39,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
if (!_authorizer.Authorize(Permissions.ManageBlogs, T("Not allowed to create blogs")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
Blog blog = _services.ContentManager.New<Blog>("blog");
|
||||
Blog blog = _services.ContentManager.New<Blog>(BlogDriver.ContentType.Name);
|
||||
|
||||
if (blog == null)
|
||||
return new NotFoundResult();
|
||||
@@ -57,7 +57,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
if (!_authorizer.Authorize(Permissions.ManageBlogs, T("Couldn't create blog")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
model.Blog = _services.ContentManager.UpdateEditorModel(_services.ContentManager.New<Blog>("blog"), this);
|
||||
model.Blog = _services.ContentManager.UpdateEditorModel(_services.ContentManager.New<Blog>(BlogDriver.ContentType.Name), this);
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
return View(model);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Orchard.Blogs.Models;
|
||||
using Orchard.Blogs.Services;
|
||||
using Orchard.Blogs.ViewModels;
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
if (blog == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
var blogPost = _services.ContentManager.New<BlogPost>("blogpost");
|
||||
var blogPost = _services.ContentManager.New<BlogPost>(BlogPostDriver.ContentType.Name);
|
||||
blogPost.Blog = blog;
|
||||
|
||||
var model = new CreateBlogPostViewModel {
|
||||
@@ -74,19 +74,21 @@ namespace Orchard.Blogs.Controllers {
|
||||
}
|
||||
}
|
||||
|
||||
model.BlogPost = _services.ContentManager.UpdateEditorModel(_services.ContentManager.New<BlogPost>("blogpost"), this);
|
||||
model.BlogPost = _services.ContentManager.UpdateEditorModel(_services.ContentManager.New<BlogPost>(BlogPostDriver.ContentType.Name), this);
|
||||
model.BlogPost.Item.Blog = blog;
|
||||
if (!publishNow && publishDate != null)
|
||||
model.BlogPost.Item.Published = publishDate.Value;
|
||||
|
||||
if (!ModelState.IsValid) {
|
||||
_services.TransactionManager.Cancel();
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//TODO: (erikpo) Evaluate if publish options should be moved into create or out of create to keep it clean
|
||||
_services.ContentManager.Create(model.BlogPost.Item.ContentItem, publishNow ? VersionOptions.Published : VersionOptions.Draft);
|
||||
//todo: (heskew) make it so we no longer need to set as draft on create then publish (all to get the publishing & published events fired)
|
||||
_services.ContentManager.Create(model.BlogPost.Item.ContentItem, VersionOptions.Draft);
|
||||
|
||||
if (publishNow)
|
||||
_services.ContentManager.Publish(model.BlogPost.Item.ContentItem);
|
||||
|
||||
//TEMP: (erikpo) ensure information has committed for this record
|
||||
var session = _sessionLocator.For(typeof(ContentItemRecord));
|
||||
@@ -95,7 +97,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
return Redirect(Url.BlogPost(blogSlug, model.BlogPost.Item.As<RoutableAspect>().Slug));
|
||||
}
|
||||
|
||||
public ActionResult Edit(string blogSlug, string postSlug) {
|
||||
public ActionResult Edit(string blogSlug, int postId) {
|
||||
if (!_services.Authorizer.Authorize(Permissions.EditBlogPost, T("Couldn't edit blog post")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
@@ -105,7 +107,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
if (blog == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
BlogPost post = _blogPostService.Get(blog, postSlug, VersionOptions.Latest);
|
||||
BlogPost post = _blogPostService.Get(postId, VersionOptions.Latest);
|
||||
|
||||
if (post == null)
|
||||
return new NotFoundResult();
|
||||
@@ -118,7 +120,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
}
|
||||
|
||||
[HttpPost, ActionName("Edit")]
|
||||
public ActionResult EditPOST(string blogSlug, string postSlug) {
|
||||
public ActionResult EditPOST(string blogSlug, int postId) {
|
||||
if (!_services.Authorizer.Authorize(Permissions.EditBlogPost, T("Couldn't edit blog post")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
@@ -130,7 +132,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
if (blog == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
BlogPost post = _blogPostService.Get(blog, postSlug, VersionOptions.Latest);
|
||||
BlogPost post = _blogPostService.Get(postId, VersionOptions.Latest);
|
||||
|
||||
if (post == null)
|
||||
return new NotFoundResult();
|
||||
@@ -172,13 +174,13 @@ namespace Orchard.Blogs.Controllers {
|
||||
_services.Notifier.Information(T("Blog post information updated."));
|
||||
|
||||
if (isDraft) {
|
||||
return Redirect(Url.BlogPostEdit(blog.Slug, post.Slug));
|
||||
return Redirect(Url.BlogPostEdit(blog.Slug, post.Id));
|
||||
}
|
||||
return Redirect(Url.BlogForAdmin(blog.Slug));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Delete(string blogSlug, string postSlug) {
|
||||
public ActionResult Delete(string blogSlug, int postId) {
|
||||
//refactoring: test PublishBlogPost/PublishOthersBlogPost in addition if published
|
||||
if (!_services.Authorizer.Authorize(Permissions.DeleteBlogPost, T("Couldn't delete blog post")))
|
||||
return new HttpUnauthorizedResult();
|
||||
@@ -189,7 +191,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
if (blog == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
BlogPost post = _blogPostService.Get(blog, postSlug, VersionOptions.Latest);
|
||||
BlogPost post = _blogPostService.Get(postId, VersionOptions.Latest);
|
||||
|
||||
if (post == null)
|
||||
return new NotFoundResult();
|
||||
@@ -201,7 +203,8 @@ namespace Orchard.Blogs.Controllers {
|
||||
return Redirect(Url.BlogForAdmin(blogSlug));
|
||||
}
|
||||
|
||||
public ActionResult Publish(string blogSlug, string postSlug) {
|
||||
[HttpPost]
|
||||
public ActionResult Publish(string blogSlug, int postId) {
|
||||
if (!_services.Authorizer.Authorize(Permissions.PublishBlogPost, T("Couldn't publish blog post")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
@@ -211,7 +214,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
if (blog == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
BlogPost post = _blogPostService.Get(blog, postSlug, VersionOptions.Latest);
|
||||
BlogPost post = _blogPostService.Get(postId, VersionOptions.Latest);
|
||||
|
||||
if (post == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
@@ -111,7 +111,8 @@ namespace Orchard.Blogs.Controllers {
|
||||
//todo: (heskew) need better messages
|
||||
_orchardServices.Notifier.Warning(T("A different blog post is already published with this same slug."));
|
||||
|
||||
if (post.ContentItem.VersionRecord == null || post.ContentItem.VersionRecord.Published) {
|
||||
if (post.ContentItem.VersionRecord == null || post.ContentItem.VersionRecord.Published)
|
||||
{
|
||||
var originalSlug = post.Slug;
|
||||
//todo: (heskew) make auto-uniqueness optional
|
||||
post.Slug = _routableService.GenerateUniqueSlug(post.Slug, slugsLikeThis);
|
||||
|
||||
@@ -50,16 +50,16 @@ namespace Orchard.Blogs.Extensions {
|
||||
return urlHelper.Action("Create", "BlogPostAdmin", new {blogSlug, area = "Orchard.Blogs"});
|
||||
}
|
||||
|
||||
public static string BlogPostEdit(this UrlHelper urlHelper, string blogSlug, string postSlug) {
|
||||
return urlHelper.Action("Edit", "BlogPostAdmin", new {blogSlug, postSlug, area = "Orchard.Blogs"});
|
||||
public static string BlogPostEdit(this UrlHelper urlHelper, string blogSlug, int postId) {
|
||||
return urlHelper.Action("Edit", "BlogPostAdmin", new {blogSlug, postId, area = "Orchard.Blogs"});
|
||||
}
|
||||
|
||||
public static string BlogPostDelete(this UrlHelper urlHelper, string blogSlug, string postSlug) {
|
||||
return urlHelper.Action("Delete", "BlogPostAdmin", new {blogSlug, postSlug, area = "Orchard.Blogs"});
|
||||
public static string BlogPostDelete(this UrlHelper urlHelper, string blogSlug, int postId) {
|
||||
return urlHelper.Action("Delete", "BlogPostAdmin", new {blogSlug, postId, area = "Orchard.Blogs"});
|
||||
}
|
||||
|
||||
public static string BlogPostPublish(this UrlHelper urlHelper, string blogSlug, string postSlug) {
|
||||
return urlHelper.Action("Publish", "BlogPostAdmin", new { blogSlug, postSlug, area = "Orchard.Blogs" });
|
||||
public static string BlogPostPublish(this UrlHelper urlHelper, string blogSlug, int postId) {
|
||||
return urlHelper.Action("Publish", "BlogPostAdmin", new { blogSlug, postId, area = "Orchard.Blogs" });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.Blogs.Controllers;
|
||||
using Orchard.Blogs.Services;
|
||||
@@ -7,12 +8,24 @@ using Orchard.ContentManagement;
|
||||
using Orchard.Core.Common.Models;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Core.Common.Records;
|
||||
using Orchard.Core.Common.Services;
|
||||
using Orchard.Data;
|
||||
using Orchard.Localization;
|
||||
using Orchard.UI.Notify;
|
||||
|
||||
namespace Orchard.Blogs.Models {
|
||||
[UsedImplicitly]
|
||||
public class BlogPostHandler : ContentHandler {
|
||||
public BlogPostHandler(IRepository<CommonVersionRecord> commonRepository, IBlogPostService blogPostService) {
|
||||
private readonly IBlogPostService _blogPostService;
|
||||
private readonly IRoutableService _routableService;
|
||||
private readonly IOrchardServices _orchardServices;
|
||||
|
||||
public BlogPostHandler(IRepository<CommonVersionRecord> commonRepository, IBlogPostService blogPostService, IRoutableService routableService, IOrchardServices orchardServices) {
|
||||
_blogPostService = blogPostService;
|
||||
_routableService = routableService;
|
||||
_orchardServices = orchardServices;
|
||||
T = NullLocalizer.Instance;
|
||||
|
||||
Filters.Add(new ActivatingFilter<BlogPost>(BlogPostDriver.ContentType.Name));
|
||||
Filters.Add(new ActivatingFilter<CommonAspect>(BlogPostDriver.ContentType.Name));
|
||||
Filters.Add(new ActivatingFilter<RoutableAspect>(BlogPostDriver.ContentType.Name));
|
||||
@@ -24,7 +37,7 @@ namespace Orchard.Blogs.Models {
|
||||
// Ensure we get the "right" set of published posts for the blog
|
||||
blog.ContentItem.ContentManager.Flush();
|
||||
|
||||
var posts = blogPostService.Get(blog, VersionOptions.Published).ToList();
|
||||
var posts = _blogPostService.Get(blog, VersionOptions.Published).ToList();
|
||||
blog.PostCount = posts.Count;
|
||||
});
|
||||
|
||||
@@ -33,10 +46,30 @@ namespace Orchard.Blogs.Models {
|
||||
OnVersioned<BlogPost>((context, bp1, bp2) => updateBlogPostCount(bp2.Blog));
|
||||
OnRemoved<BlogPost>((context, bp) => updateBlogPostCount(bp.Blog));
|
||||
|
||||
OnPublished<BlogPost>((context, bp) => ProcessSlug(bp));
|
||||
|
||||
OnRemoved<Blog>(
|
||||
(context, b) =>
|
||||
blogPostService.Get(context.ContentItem.As<Blog>()).ToList().ForEach(
|
||||
blogPost => context.ContentManager.Remove(blogPost.ContentItem)));
|
||||
}
|
||||
|
||||
Localizer T { get; set; }
|
||||
|
||||
private void ProcessSlug(BlogPost post) {
|
||||
_routableService.FillSlug(post.As<RoutableAspect>());
|
||||
|
||||
var slugsLikeThis = _blogPostService.Get(post.Blog, VersionOptions.Published).Where(
|
||||
p => p.Slug.StartsWith(post.Slug, StringComparison.OrdinalIgnoreCase) &&
|
||||
p.Id != post.Id).Select(p => p.Slug);
|
||||
|
||||
//todo: (heskew) need better messages
|
||||
if (slugsLikeThis.Count() > 0) {
|
||||
//todo: (heskew) need better messages
|
||||
var originalSlug = post.Slug;
|
||||
post.Slug = _routableService.GenerateUniqueSlug(post.Slug, slugsLikeThis);
|
||||
_orchardServices.Notifier.Warning(T("A different blog post is already published with this same slug ({0}) so a unique slug ({1}) was generated for this post.", originalSlug, post.Slug));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ namespace Orchard.Blogs {
|
||||
},
|
||||
new RouteDescriptor {
|
||||
Route = new Route(
|
||||
"Admin/Blogs/{blogSlug}/Posts/{postSlug}/Edit",
|
||||
"Admin/Blogs/{blogSlug}/Posts/{postId}/Edit",
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"},
|
||||
{"controller", "BlogPostAdmin"},
|
||||
@@ -117,7 +117,7 @@ namespace Orchard.Blogs {
|
||||
},
|
||||
new RouteDescriptor {
|
||||
Route = new Route(
|
||||
"Admin/Blogs/{blogSlug}/Posts/{postSlug}/Delete",
|
||||
"Admin/Blogs/{blogSlug}/Posts/{postId}/Delete",
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"},
|
||||
{"controller", "BlogPostAdmin"},
|
||||
@@ -131,6 +131,22 @@ namespace Orchard.Blogs {
|
||||
},
|
||||
new MvcRouteHandler())
|
||||
},
|
||||
new RouteDescriptor {
|
||||
Route = new Route(
|
||||
"Admin/Blogs/{blogSlug}/Posts/{postId}/Publish",
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"},
|
||||
{"controller", "BlogPostAdmin"},
|
||||
{"action", "Publish"}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"blogSlug", new IsBlogConstraint(_containerProvider)}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"}
|
||||
},
|
||||
new MvcRouteHandler())
|
||||
},
|
||||
new RouteDescriptor {
|
||||
Route = new Route(
|
||||
"Admin/Blogs",
|
||||
|
||||
@@ -25,6 +25,14 @@ namespace Orchard.Blogs.Services {
|
||||
SingleOrDefault().As<BlogPost>();
|
||||
}
|
||||
|
||||
public BlogPost Get(int id) {
|
||||
return Get(id, VersionOptions.Published);
|
||||
}
|
||||
|
||||
public BlogPost Get(int id, VersionOptions versionOptions) {
|
||||
return _contentManager.Get<BlogPost>(id, versionOptions);
|
||||
}
|
||||
|
||||
public IEnumerable<BlogPost> Get(Blog blog) {
|
||||
return Get(blog, VersionOptions.Published);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ namespace Orchard.Blogs.Services {
|
||||
public interface IBlogPostService : IDependency {
|
||||
BlogPost Get(Blog blog, string slug);
|
||||
BlogPost Get(Blog blog, string slug, VersionOptions versionOptions);
|
||||
BlogPost Get(int id);
|
||||
BlogPost Get(int id, VersionOptions versionOptions);
|
||||
IEnumerable<BlogPost> Get(Blog blog);
|
||||
IEnumerable<BlogPost> Get(Blog blog, VersionOptions versionOptions);
|
||||
IEnumerable<BlogPost> Get(Blog blog, ArchiveData archiveData);
|
||||
|
||||
@@ -6,19 +6,23 @@
|
||||
<%@ Import Namespace="Orchard.Mvc.ViewModels"%>
|
||||
<%@ Import Namespace="Orchard.Blogs.Extensions"%>
|
||||
<%@ Import Namespace="Orchard.Blogs.Models"%>
|
||||
<h2><%=Html.Link(Html.Encode(Model.Item.Title), Url.BlogPostEdit(Model.Item.Blog.Slug, Model.Item.Slug)) %></h2>
|
||||
<h2><%=Html.Link(Html.Encode(Model.Item.Title), Url.BlogPostEdit(Model.Item.Blog.Slug, Model.Item.Id)) %></h2>
|
||||
<div class="meta"><%=Html.PublishedState(Model.Item) %> | <%Html.Zone("meta");%></div>
|
||||
<div class="content"><%=Model.Item.As<BodyAspect>().Text ?? string.Format("<p><em>{0}</em></p>", _Encoded("there's no content for this blog post"))%></div>
|
||||
<ul class="actions">
|
||||
<li class="construct">
|
||||
<a href="<%=Url.BlogPostEdit(Model.Item.Blog.Slug, Model.Item.Slug) %>" class="ibutton edit" title="<%=_Encoded("Edit Post")%>"><%=_Encoded("Edit Post")%></a>
|
||||
<a href="<%=Url.BlogPostEdit(Model.Item.Blog.Slug, Model.Item.Id) %>" class="ibutton edit" title="<%=_Encoded("Edit Post")%>"><%=_Encoded("Edit Post")%></a>
|
||||
<a href="<%=Url.BlogPost(Model.Item.Blog.Slug, Model.Item.Slug) %>" class="ibutton view" title="<%=_Encoded("View Post")%>"><%=_Encoded("View Post")%></a><%
|
||||
if (Model.Item.ContentItem.VersionRecord.Published == false) { // todo: (heskew) be smart about this and maybe have other contextual actions - including view/preview for view up there ^^ %>
|
||||
<a href="<%=Url.BlogPostPublish(Model.Item.Blog.Slug, Model.Item.Slug) %>" class="ibutton publish" title="<%=_Encoded("Publish Post Now")%>"><%=_Encoded("Publish Post Now")%></a>
|
||||
<% } %>
|
||||
if (Model.Item.ContentItem.VersionRecord.Published == false) { // todo: (heskew) be smart about this and maybe have other contextual actions - including view/preview for view up there ^^
|
||||
using (Html.BeginFormAntiForgeryPost(Url.BlogPostPublish(Model.Item.Blog.Slug, Model.Item.Id), FormMethod.Post, new { @class = "inline" })) { %>
|
||||
<fieldset>
|
||||
<button type="submit" class="ibutton publish" title="<%=_Encoded("Publish Post Now") %>"><%=_Encoded("Publish Post Now")%></button>
|
||||
</fieldset><%
|
||||
}
|
||||
} %>
|
||||
</li>
|
||||
<li class="destruct">
|
||||
<% using (Html.BeginFormAntiForgeryPost(Url.BlogPostDelete(Model.Item.Blog.Slug, Model.Item.Slug), FormMethod.Post, new { @class = "inline" })) { %>
|
||||
<% using (Html.BeginFormAntiForgeryPost(Url.BlogPostDelete(Model.Item.Blog.Slug, Model.Item.Id), FormMethod.Post, new { @class = "inline" })) { %>
|
||||
<fieldset>
|
||||
<button type="submit" class="ibutton remove" title="<%=_Encoded("Remove Post") %>"><%=_Encoded("Remove Post") %></button>
|
||||
</fieldset><%
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<%@ Import Namespace="Orchard.Blogs.Extensions"%>
|
||||
<%@ Import Namespace="Orchard.Blogs.Models"%>
|
||||
<h1><%=Html.TitleForPage(Model.Item.Title)%></h1>
|
||||
<div class="manage"><a href="<%=Url.BlogPostEdit(Model.Item.Blog.Slug, Model.Item.Slug) %>" class="ibutton edit"><%=_Encoded("Edit") %></a></div>
|
||||
<div class="manage"><a href="<%=Url.BlogPostEdit(Model.Item.Blog.Slug, Model.Item.Id) %>" class="ibutton edit"><%=_Encoded("Edit") %></a></div>
|
||||
<div class="metadata">
|
||||
<% if (Model.Item.Creator != null) {
|
||||
%><div class="posted"><%=_Encoded("Posted by {0} {1}", Model.Item.Creator.UserName, Html.PublishedWhen(Model.Item)) %></div><%
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
var blogPost = Model.BlogPost.Item;
|
||||
var bodyViewModelModel = new BodyDisplayViewModel { BodyAspect = blogPost.ContentItem.As<BodyAspect>() };
|
||||
var hasComments = blogPost.ContentItem.As<HasComments>(); %>
|
||||
<div class="manage"><a href="<%=Url.BlogPostEdit(blogPost.Blog.Slug, blogPost.Slug) %>" class="ibutton edit"><%=_Encoded("edit") %></a></div>
|
||||
<div class="manage"><a href="<%=Url.BlogPostEdit(blogPost.Blog.Slug, blogPost.Id) %>" class="ibutton edit"><%=_Encoded("edit") %></a></div>
|
||||
<h1><%=Html.TitleForPage(blogPost.Title)%></h1>
|
||||
<div class="metadata">
|
||||
<% if (blogPost.Creator != null) {
|
||||
|
||||
Reference in New Issue
Block a user