diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs index 569517dac..bf06b98ac 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs @@ -70,7 +70,8 @@ namespace Orchard.Blogs.Services { Convert.ToString(context.Request.Params[0].Value), Convert.ToString(context.Request.Params[1].Value), Convert.ToString(context.Request.Params[2].Value), - Convert.ToInt32(context.Request.Params[3].Value)); + Convert.ToInt32(context.Request.Params[3].Value), + context._drivers); context.Response = new XRpcMethodResponse().Add(result); } @@ -147,7 +148,8 @@ namespace Orchard.Blogs.Services { string blogId, string userName, string password, - int numberOfPosts) { + int numberOfPosts, + IEnumerable drivers) { IUser user = ValidateUser(userName, password); @@ -161,7 +163,12 @@ namespace Orchard.Blogs.Services { var array = new XRpcArray(); foreach (var blogPost in _blogPostService.Get(blog, 0, numberOfPosts, VersionOptions.Latest)) { - array.Add(CreateBlogStruct(blogPost, urlHelper)); + var postStruct = CreateBlogStruct(blogPost, urlHelper); + + foreach (var driver in drivers) + driver.Process(postStruct); + + array.Add(postStruct); } return array; } @@ -210,7 +217,8 @@ namespace Orchard.Blogs.Services { _contentManager.Create(blogPost.ContentItem, VersionOptions.Draft); - if (publish) + var publishedUtc = content.Optional("dateCreated"); + if (publish && (publishedUtc == null || publishedUtc <= DateTime.UtcNow)) _blogPostService.Publish(blogPost); foreach (var driver in drivers) @@ -253,11 +261,21 @@ namespace Orchard.Blogs.Services { var description = content.Optional("description"); var slug = content.Optional("wp_slug"); - blogPost.Title = title; - blogPost.Slug = slug; - blogPost.Text = description; + // BodyPart + if (blogPost.Is()) { + blogPost.As().Text = description; + } - if (publish) + //RoutePart + if (blogPost.Is()) { + blogPost.As().Title = title; + blogPost.As().Slug = slug; + _routableService.FillSlugFromTitle(blogPost.As()); + blogPost.As().Path = blogPost.As().GetPathWithSlug(blogPost.As().Slug); + } + + var publishedUtc = content.Optional("dateCreated"); + if (publish && (publishedUtc == null || publishedUtc <= DateTime.UtcNow)) _blogPostService.Publish(blogPost); foreach (var driver in drivers) @@ -292,14 +310,20 @@ namespace Orchard.Blogs.Services { private static XRpcStruct CreateBlogStruct(BlogPostPart blogPostPart, UrlHelper urlHelper) { var url = urlHelper.AbsoluteAction(() => urlHelper.BlogPost(blogPostPart)); - return new XRpcStruct() + var blogStruct = new XRpcStruct() .Set("postid", blogPostPart.Id) - .Set("dateCreated", blogPostPart.PublishedUtc) .Set("title", blogPostPart.Title) .Set("wp_slug", blogPostPart.Slug) .Set("description", blogPostPart.Text) .Set("link", url) .Set("permaLink", url); + + if (blogPostPart.PublishedUtc != null) { + blogStruct.Set("dateCreated", blogPostPart.PublishedUtc); + blogStruct.Set("date_created_gmt", blogPostPart.PublishedUtc); + } + + return blogStruct; } } } diff --git a/src/Orchard.Web/Modules/Orchard.PublishLater/Orchard.PublishLater.csproj b/src/Orchard.Web/Modules/Orchard.PublishLater/Orchard.PublishLater.csproj index c0bdc79e1..c1fb4b84f 100644 --- a/src/Orchard.Web/Modules/Orchard.PublishLater/Orchard.PublishLater.csproj +++ b/src/Orchard.Web/Modules/Orchard.PublishLater/Orchard.PublishLater.csproj @@ -44,6 +44,8 @@ ..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll + + @@ -59,6 +61,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.PublishLater/Services/XmlRpcHandler.cs b/src/Orchard.Web/Modules/Orchard.PublishLater/Services/XmlRpcHandler.cs new file mode 100644 index 000000000..5b825e326 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.PublishLater/Services/XmlRpcHandler.cs @@ -0,0 +1,170 @@ +using System; +using System.Collections.Generic; +using System.Xml.Linq; +using Orchard.ContentManagement; +using Orchard.Core.Contents; +using Orchard.Core.XmlRpc; +using Orchard.Core.XmlRpc.Models; +using Orchard.Localization; +using Orchard.PublishLater.Models; +using Orchard.Security; +using Orchard.Tasks.Scheduling; + +namespace Orchard.PublishLater.Services { + public class XmlRpcHandler : IXmlRpcHandler { + private readonly IContentManager _contentManager; + private readonly IPublishingTaskManager _publishingTaskManager; + private readonly IMembershipService _membershipService; + private readonly IAuthorizationService _authorizationService; + + public XmlRpcHandler(IContentManager contentManager, + IPublishingTaskManager publishingTaskManager, + IMembershipService membershipService, + IAuthorizationService authorizationService) { + _contentManager = contentManager; + _publishingTaskManager = publishingTaskManager; + _membershipService = membershipService; + _authorizationService = authorizationService; + T = NullLocalizer.Instance; + } + + public Localizer T { get; set; } + + public void SetCapabilities(XElement options) { + const string manifestUri = "http://schemas.microsoft.com/wlw/manifest/weblog"; + options.SetElementValue(XName.Get("supportsCustomDate", manifestUri), "Yes"); + } + + public void Process(XmlRpcContext context) { + switch (context.Request.MethodName) { + case "metaWeblog.newPost": + MetaWeblogSetCustomPublishedDate( + GetId(context.Response), + Convert.ToString(context.Request.Params[0].Value), + Convert.ToString(context.Request.Params[1].Value), + Convert.ToString(context.Request.Params[2].Value), + (XRpcStruct)context.Request.Params[3].Value, + Convert.ToBoolean(context.Request.Params[4].Value), + context._drivers); + break; + case "metaWeblog.editPost": + MetaWeblogSetCustomPublishedDate( + GetId(context.Response), + Convert.ToString(context.Request.Params[0].Value), + Convert.ToString(context.Request.Params[1].Value), + Convert.ToString(context.Request.Params[2].Value), + (XRpcStruct)context.Request.Params[3].Value, + Convert.ToBoolean(context.Request.Params[4].Value), + context._drivers); + break; + case "metaWeblog.getPost": + MetaWeblogGetCustomPublishedDate( + GetPost(context.Response), + Convert.ToInt32(context.Request.Params[0].Value), + Convert.ToString(context.Request.Params[1].Value), + Convert.ToString(context.Request.Params[2].Value), + context._drivers); + break; + case "metaWeblog.getRecentPosts": + MetaWeblogGetCustomPublishedDate( + GetPost(context.Response), + Convert.ToInt32(context.Request.Params[0].Value), + Convert.ToString(context.Request.Params[1].Value), + Convert.ToString(context.Request.Params[2].Value), + context._drivers); + break; + } + } + + private void MetaWeblogGetCustomPublishedDate(XRpcStruct postStruct, int itemId, string userName, string password, ICollection drivers) { + if (itemId < 1) + return; + + var driver = new XmlRpcDriver(item => { + var post = item as XRpcStruct; + if (post == null) + return; + + var postId = post.Optional("postid"); + var contentItem = _contentManager.Get(postId, VersionOptions.Latest); + if (contentItem == null) + return; + + var publishedUtc = contentItem.As().ScheduledPublishUtc.Value; + if (publishedUtc == null || publishedUtc <= DateTime.UtcNow) + return; + + post.Set("dateCreated", publishedUtc); + post.Set("date_created_gmt", publishedUtc); + }); + + if (postStruct != null) + driver.Process(postStruct); + else + drivers.Add(driver); + } + + private void MetaWeblogSetCustomPublishedDate(int contentItemId, string appKey, string userName, string password, XRpcStruct content, bool publish, ICollection drivers) { + var user = ValidateUser(userName, password); + if (user == null) + return; + + var publishedUtc = content.Optional("dateCreated"); + if (publishedUtc == null || publishedUtc <= DateTime.UtcNow) // only post-dating/scheduling of content with the PublishLaterPart + return; + + var driver = new XmlRpcDriver(item => { + if (!(item is int)) + return; + + var id = (int)item; + var contentItem = _contentManager.Get(id, VersionOptions.Latest); + if (contentItem == null || !contentItem.Is()) + return; + + _authorizationService.CheckAccess(Permissions.PublishOthersContent, user, null); + + contentItem.As().ScheduledPublishUtc.Value = publishedUtc; + _publishingTaskManager.Publish(contentItem, (DateTime)publishedUtc); + }); + + if (contentItemId > 0) + driver.Process(contentItemId); + else + drivers.Add(driver); + } + + private static XRpcStruct GetPost(XRpcMethodResponse response) { + return response != null && response.Params.Count == 1 && response.Params[0].Value is XRpcStruct + ? response.Params[0].Value as XRpcStruct + : null; + } + + private static int GetId(XRpcMethodResponse response) { + return response != null && response.Params.Count == 1 && response.Params[0].Value is int + ? Convert.ToInt32(response.Params[0].Value) + : 0; + } + + private IUser ValidateUser(string userName, string password) { + IUser user = _membershipService.ValidateUser(userName, password); + if (user == null) { + throw new OrchardCoreException(T("The username or e-mail or password provided is incorrect.")); + } + + return user; + } + + public class XmlRpcDriver : IXmlRpcDriver { + private readonly Action _process; + + public XmlRpcDriver(Action process) { + _process = process; + } + + public void Process(object item) { + _process(item); + } + } + } +} \ No newline at end of file