From ff60c81e65d4b765910219d6f3e722640b44189c Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Mon, 13 Dec 2010 17:43:17 -0800 Subject: [PATCH 1/5] Updating to Azure SDK 1.3 --HG-- branch : dev --- AzurePackage.proj | 22 +-------------- ClickToRunAzureInDevFabric.cmd | 5 ---- src/Orchard.Azure.Tests/App.config | 2 +- .../Orchard.Azure.Tests.csproj | 2 +- .../ServiceConfiguration.cscfg | 2 +- .../ServiceDefinition.csdef | 11 ++++++-- .../Orchard.Azure.Web/Global.asax.cs | 20 ++++++++++++- .../Orchard.Azure.Web.csproj | 3 +- .../Orchard.Azure.Web/WebRole.cs | 28 ------------------- src/Orchard.Azure/Orchard.Azure.csproj | 2 +- 10 files changed, 34 insertions(+), 63 deletions(-) delete mode 100644 ClickToRunAzureInDevFabric.cmd delete mode 100644 src/Orchard.Azure/Orchard.Azure.Web/WebRole.cs diff --git a/AzurePackage.proj b/AzurePackage.proj index a5bc7ccfa..9ea83c86e 100644 --- a/AzurePackage.proj +++ b/AzurePackage.proj @@ -72,8 +72,6 @@ - - @@ -113,24 +111,6 @@ XPath="/log4net/root/priority/@value" Value="ERROR" /> - - - - - - - - - - - - diff --git a/ClickToRunAzureInDevFabric.cmd b/ClickToRunAzureInDevFabric.cmd deleted file mode 100644 index c0a35a30e..000000000 --- a/ClickToRunAzureInDevFabric.cmd +++ /dev/null @@ -1,5 +0,0 @@ -SET CDIR = %CD% -call "%ProgramFiles%\Windows Azure SDK\v1.2\bin\setenv.cmd" -csrun /devstore -csrun /run:"%CDIR %\build\Compile\Orchard.Azure.CloudService.csx";"%CDIR %\src\Orchard.Azure\Orchard.Azure.CloudService\ServiceConfiguration.cscfg" /launchbrowser -pause \ No newline at end of file diff --git a/src/Orchard.Azure.Tests/App.config b/src/Orchard.Azure.Tests/App.config index dcb9cb146..41aa17680 100644 --- a/src/Orchard.Azure.Tests/App.config +++ b/src/Orchard.Azure.Tests/App.config @@ -1,7 +1,7 @@ - + diff --git a/src/Orchard.Azure.Tests/Orchard.Azure.Tests.csproj b/src/Orchard.Azure.Tests/Orchard.Azure.Tests.csproj index ecdce0f39..355147332 100644 --- a/src/Orchard.Azure.Tests/Orchard.Azure.Tests.csproj +++ b/src/Orchard.Azure.Tests/Orchard.Azure.Tests.csproj @@ -55,7 +55,7 @@ - + False ..\..\lib\moq\Moq.dll diff --git a/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.cscfg b/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.cscfg index 0e71f7efb..9600d5e76 100644 --- a/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.cscfg +++ b/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.cscfg @@ -1,5 +1,5 @@ - + diff --git a/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceDefinition.csdef b/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceDefinition.csdef index 0cc371c69..3503cc02c 100644 --- a/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceDefinition.csdef +++ b/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceDefinition.csdef @@ -1,11 +1,18 @@  + + + + + + + - + - + \ No newline at end of file diff --git a/src/Orchard.Azure/Orchard.Azure.Web/Global.asax.cs b/src/Orchard.Azure/Orchard.Azure.Web/Global.asax.cs index 2b3cdbad3..bd2b37c44 100644 --- a/src/Orchard.Azure/Orchard.Azure.Web/Global.asax.cs +++ b/src/Orchard.Azure/Orchard.Azure.Web/Global.asax.cs @@ -1,7 +1,10 @@ -using System.Web; +using System.Linq; +using System.Web; using System.Web.Mvc; using System.Web.Routing; using Autofac; +using Microsoft.WindowsAzure; +using Microsoft.WindowsAzure.ServiceRuntime; using Orchard.Environment; namespace Orchard.Azure.Web { @@ -16,6 +19,21 @@ namespace Orchard.Azure.Web { } protected void Application_Start() { + CloudStorageAccount.SetConfigurationSettingPublisher( + (configName, configSetter) => + configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)) + ); + + // For information on handling configuration changes + // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357. + RoleEnvironment.Changing += (sender, e) => { + // If a configuration setting is changing + if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange)) { + // Set e.Cancel to true to restart this role instance + e.Cancel = true; + } + }; + RegisterRoutes(RouteTable.Routes); _host = OrchardStarter.CreateHost(MvcSingletons); diff --git a/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj b/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj index 31d043fba..0550e42a9 100644 --- a/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj +++ b/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj @@ -58,7 +58,7 @@ False - + ..\..\..\lib\fluentnhibernate\NHibernate.ByteCode.Castle.dll @@ -144,7 +144,6 @@ Global.asax - diff --git a/src/Orchard.Azure/Orchard.Azure.Web/WebRole.cs b/src/Orchard.Azure/Orchard.Azure.Web/WebRole.cs deleted file mode 100644 index 4db62c516..000000000 --- a/src/Orchard.Azure/Orchard.Azure.Web/WebRole.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Linq; -using Microsoft.WindowsAzure; -using Microsoft.WindowsAzure.ServiceRuntime; - -namespace Orchard.Azure.Web { - public class WebRole : RoleEntryPoint { - public override bool OnStart() { - CloudStorageAccount.SetConfigurationSettingPublisher( - (configName, configSetter) => - configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)) - ); - - // For information on handling configuration changes - // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357. - RoleEnvironment.Changing += RoleEnvironmentChanging; - - return base.OnStart(); - } - - private static void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e) { - // If a configuration setting is changing - if ( e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange) ) { - // Set e.Cancel to true to restart this role instance - e.Cancel = true; - } - } - } -} diff --git a/src/Orchard.Azure/Orchard.Azure.csproj b/src/Orchard.Azure/Orchard.Azure.csproj index b70945429..01dd0d140 100644 --- a/src/Orchard.Azure/Orchard.Azure.csproj +++ b/src/Orchard.Azure/Orchard.Azure.csproj @@ -54,7 +54,7 @@ - + 3.5 From 711306743719e6ec6d39bff7c442f7841d380f96 Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Tue, 14 Dec 2010 11:49:42 -0800 Subject: [PATCH 2/5] Fixing errors that Live Writer was logging on the client. Fixing errors that Live Writer was having with our datetime format, that we were having with the datetime string Live Writer was giving us and correctly setting an empty response to metaWeblog.getCategories from Orchard.Tags --HG-- branch : dev --- .../Core/XmlRpc/Controllers/LiveWriterController.cs | 3 ++- src/Orchard.Web/Core/XmlRpc/Services/XmlRpcReader.cs | 5 ++++- src/Orchard.Web/Core/XmlRpc/Services/XmlRpcWriter.cs | 4 ++-- .../Modules/Orchard.Tags/Services/XmlRpcHandler.cs | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Orchard.Web/Core/XmlRpc/Controllers/LiveWriterController.cs b/src/Orchard.Web/Core/XmlRpc/Controllers/LiveWriterController.cs index 439f883a7..4b3f0885a 100644 --- a/src/Orchard.Web/Core/XmlRpc/Controllers/LiveWriterController.cs +++ b/src/Orchard.Web/Core/XmlRpc/Controllers/LiveWriterController.cs @@ -27,7 +27,8 @@ namespace Orchard.Core.XmlRpc.Controllers { new XElement(XName.Get("clientType", ManifestUri), "Metaweblog"), new XElement(XName.Get("supportsKeywords", ManifestUri), "No"), new XElement(XName.Get("supportsCategories", ManifestUri), "No"), - new XElement(XName.Get("supportsFileUpload", ManifestUri), "No")); + new XElement(XName.Get("supportsFileUpload", ManifestUri), "No"), + new XElement(XName.Get("supportsCustomDate", ManifestUri), "No")); foreach (var handler in _xmlRpcHandlers) handler.SetCapabilities(options); diff --git a/src/Orchard.Web/Core/XmlRpc/Services/XmlRpcReader.cs b/src/Orchard.Web/Core/XmlRpc/Services/XmlRpcReader.cs index dd641f443..90fb19c95 100644 --- a/src/Orchard.Web/Core/XmlRpc/Services/XmlRpcReader.cs +++ b/src/Orchard.Web/Core/XmlRpc/Services/XmlRpcReader.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Xml.Linq; using Orchard.Core.XmlRpc.Models; @@ -23,7 +24,9 @@ namespace Orchard.Core.XmlRpc.Services { {"double", x=>new XRpcData { Value = (double)x }}, {"dateTime.iso8601", x=> { DateTime parsedDateTime; - if(!DateTime.TryParse(x.Value, out parsedDateTime)) { + // try parsing a "normal" datetime string then try what live writer gives us + if(!DateTime.TryParse(x.Value, out parsedDateTime) + && !DateTime.TryParseExact(x.Value, "yyyyMMddTHH:mm:ss", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None, out parsedDateTime)) { parsedDateTime = DateTime.Now; } return new XRpcData {Value = parsedDateTime}; diff --git a/src/Orchard.Web/Core/XmlRpc/Services/XmlRpcWriter.cs b/src/Orchard.Web/Core/XmlRpc/Services/XmlRpcWriter.cs index 0f1517054..65c54c425 100644 --- a/src/Orchard.Web/Core/XmlRpc/Services/XmlRpcWriter.cs +++ b/src/Orchard.Web/Core/XmlRpc/Services/XmlRpcWriter.cs @@ -18,8 +18,8 @@ namespace Orchard.Core.XmlRpc.Services { {typeof(bool), p=>new XElement("boolean", (bool)p.Value?"1":"0")}, {typeof(string), p=>new XElement("string", p.Value)}, {typeof(double), p=>new XElement("double", (double)p.Value)}, - {typeof(DateTime), p=>new XElement("dateTime.iso8601", ((DateTime)p.Value).ToString("o"))}, - {typeof(DateTime?), p=>new XElement("dateTime.iso8601", ((DateTime?)p.Value).Value.ToString("o"))}, + {typeof(DateTime), p=>new XElement("dateTime.iso8601", ((DateTime)p.Value).ToString("yyyy-MM-ddTHH:mm:ssZ"))}, + {typeof(DateTime?), p=>new XElement("dateTime.iso8601", ((DateTime?)p.Value).Value.ToString("yyyy-MM-ddTHH:mm:ssZ"))}, {typeof(byte[]), p=>new XElement("base64", Convert.ToBase64String((byte[])p.Value))}, {typeof(XRpcStruct), p=>Map((XRpcStruct)p.Value)}, {typeof(XRpcArray), p=>Map((XRpcArray)p.Value)}, diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Services/XmlRpcHandler.cs b/src/Orchard.Web/Modules/Orchard.Tags/Services/XmlRpcHandler.cs index 6084761b9..8d2e31ac4 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Services/XmlRpcHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Services/XmlRpcHandler.cs @@ -41,7 +41,7 @@ namespace Orchard.Tags.Services { switch (context.Request.MethodName) { case "metaWeblog.getCategories": // hack... because live writer still asks for it... if (context.Response == null) - context.Response = new XRpcMethodResponse(); + context.Response = new XRpcMethodResponse().Add(new XRpcArray()); break; case "wp.getTags": var tags = MetaWeblogGetTags( From f40a725c333ed42d4a04a8ef08eaa693ddf66629 Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Tue, 14 Dec 2010 13:44:14 -0800 Subject: [PATCH 3/5] More blog post published date cleanup WRT Live Writer --HG-- branch : dev --- .../Core/XmlRpc/Services/XmlRpcWriter.cs | 4 +-- .../Handlers/BlogPostPartHandler.cs | 2 +- .../Orchard.Blogs/Models/BlogPostPart.cs | 29 ++----------------- .../Orchard.Blogs/Services/XmlRpcHandler.cs | 2 +- 4 files changed, 6 insertions(+), 31 deletions(-) diff --git a/src/Orchard.Web/Core/XmlRpc/Services/XmlRpcWriter.cs b/src/Orchard.Web/Core/XmlRpc/Services/XmlRpcWriter.cs index 65c54c425..8cd9d84de 100644 --- a/src/Orchard.Web/Core/XmlRpc/Services/XmlRpcWriter.cs +++ b/src/Orchard.Web/Core/XmlRpc/Services/XmlRpcWriter.cs @@ -18,8 +18,8 @@ namespace Orchard.Core.XmlRpc.Services { {typeof(bool), p=>new XElement("boolean", (bool)p.Value?"1":"0")}, {typeof(string), p=>new XElement("string", p.Value)}, {typeof(double), p=>new XElement("double", (double)p.Value)}, - {typeof(DateTime), p=>new XElement("dateTime.iso8601", ((DateTime)p.Value).ToString("yyyy-MM-ddTHH:mm:ssZ"))}, - {typeof(DateTime?), p=>new XElement("dateTime.iso8601", ((DateTime?)p.Value).Value.ToString("yyyy-MM-ddTHH:mm:ssZ"))}, + {typeof(DateTime), p=>new XElement("dateTime.iso8601", ((DateTime)p.Value).ToString("yyyyMMddTHH:mm:ssZ"))}, + {typeof(DateTime?), p=>new XElement("dateTime.iso8601", ((DateTime?)p.Value).Value.ToString("yyyyMMddTHH:mm:ssZ"))}, {typeof(byte[]), p=>new XElement("base64", Convert.ToBase64String((byte[])p.Value))}, {typeof(XRpcStruct), p=>Map((XRpcStruct)p.Value)}, {typeof(XRpcArray), p=>Map((XRpcArray)p.Value)}, diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Handlers/BlogPostPartHandler.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Handlers/BlogPostPartHandler.cs index 34878376a..281cc498f 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Handlers/BlogPostPartHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Handlers/BlogPostPartHandler.cs @@ -51,7 +51,7 @@ namespace Orchard.Blogs.Handlers { OnCreated((context, bp) => updateBlogPostCount(bp.BlogPart)); OnPublished((context, bp) => updateBlogPostCount(bp.BlogPart)); OnUnpublished((context, bp) => updateBlogPostCount(bp.BlogPart)); - OnVersioned((context, bp1, bp2) => updateBlogPostCount(bp2.BlogPart)); + OnVersioned((context, bp1, bp2) => updateBlogPostCount(bp1.BlogPart)); OnRemoved((context, bp) => updateBlogPostCount(bp.BlogPart)); OnRemoved( diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Models/BlogPostPart.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Models/BlogPostPart.cs index c6b81028d..1de49e1ec 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Models/BlogPostPart.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Models/BlogPostPart.cs @@ -51,33 +51,8 @@ namespace Orchard.Blogs.Models { } } - public DateTime? CreatedUtc { - get { return this.As().CreatedUtc; } - } - - public DateTime? ScheduledPublishUtc { get; set; } - - private string _scheduledPublishUtcDate; - - public string ScheduledPublishUtcDate - { - get { - return !HasPublished && !string.IsNullOrEmpty(_scheduledPublishUtcDate) || !ScheduledPublishUtc.HasValue - ? _scheduledPublishUtcDate - : ScheduledPublishUtc.Value.ToShortDateString(); - } - set { _scheduledPublishUtcDate = value; } - } - - private string _scheduledPublishUtcTime; - - public string ScheduledPublishUtcTime { - get { - return !HasPublished && !string.IsNullOrEmpty(_scheduledPublishUtcTime) || !ScheduledPublishUtc.HasValue - ? _scheduledPublishUtcTime - : ScheduledPublishUtc.Value.ToShortTimeString(); - } - set { _scheduledPublishUtcTime = value; } + public DateTime? PublishedUtc { + get { return this.As().PublishedUtc; } } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs index 01190a656..569517dac 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs @@ -294,7 +294,7 @@ namespace Orchard.Blogs.Services { var url = urlHelper.AbsoluteAction(() => urlHelper.BlogPost(blogPostPart)); return new XRpcStruct() .Set("postid", blogPostPart.Id) - .Set("dateCreated", blogPostPart.CreatedUtc) + .Set("dateCreated", blogPostPart.PublishedUtc) .Set("title", blogPostPart.Title) .Set("wp_slug", blogPostPart.Slug) .Set("description", blogPostPart.Text) From 6bd7e4095883eac54e497a28c321b43bc7f4e211 Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Tue, 14 Dec 2010 13:45:58 -0800 Subject: [PATCH 4/5] Enabling pre-dating of content from Live Writer --HG-- branch : dev --- .../Core/Common/Services/XmlRpcHandler.cs | 91 +++++++++++++++++++ src/Orchard.Web/Core/Orchard.Core.csproj | 1 + 2 files changed, 92 insertions(+) create mode 100644 src/Orchard.Web/Core/Common/Services/XmlRpcHandler.cs diff --git a/src/Orchard.Web/Core/Common/Services/XmlRpcHandler.cs b/src/Orchard.Web/Core/Common/Services/XmlRpcHandler.cs new file mode 100644 index 000000000..b4a9ff5b9 --- /dev/null +++ b/src/Orchard.Web/Core/Common/Services/XmlRpcHandler.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Xml.Linq; +using Orchard.ContentManagement; +using Orchard.Core.Common.Models; +using Orchard.Core.XmlRpc; +using Orchard.Core.XmlRpc.Models; + +namespace Orchard.Core.Common.Services { + public class XmlRpcHandler : IXmlRpcHandler { + private readonly IContentManager _contentManager; + + public XmlRpcHandler(IContentManager contentManager) { + _contentManager = contentManager; + } + + 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; + } + } + + private void MetaWeblogSetCustomPublishedDate(int contentItemId, string appKey, string userName, string password, XRpcStruct content, bool publish, ICollection drivers) { + if (!publish) + return; + + var publishedUtc = content.Optional("dateCreated"); + if (publishedUtc == null || publishedUtc > DateTime.UtcNow) // only pre-dating of content with the CommonPart + 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; + + contentItem.As().PublishedUtc = publishedUtc; + }); + + if (contentItemId > 0) + driver.Process(contentItemId); + else + drivers.Add(driver); + } + + 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; + } + + 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 diff --git a/src/Orchard.Web/Core/Orchard.Core.csproj b/src/Orchard.Web/Core/Orchard.Core.csproj index 67b970439..b59372d85 100644 --- a/src/Orchard.Web/Core/Orchard.Core.csproj +++ b/src/Orchard.Web/Core/Orchard.Core.csproj @@ -62,6 +62,7 @@ + From 19846507dc2a1674ecfc01412be50c0803c520d2 Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Tue, 14 Dec 2010 15:51:48 -0800 Subject: [PATCH 5/5] Fixing scheduling of blog posts from Live Writer work item: 17041 --HG-- branch : dev --- .../Orchard.Blogs/Services/XmlRpcHandler.cs | 44 +++-- .../Orchard.PublishLater.csproj | 3 + .../Services/XmlRpcHandler.cs | 170 ++++++++++++++++++ 3 files changed, 207 insertions(+), 10 deletions(-) create mode 100644 src/Orchard.Web/Modules/Orchard.PublishLater/Services/XmlRpcHandler.cs 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