From bb3e63b9d9c2f5706253564b38cc8814914719e7 Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Wed, 17 Nov 2010 15:36:57 -0800 Subject: [PATCH] Updating XmlRpc functionality to clear up the confusion with Live Writer (WLW) and categories (since there is not category support) - updated IXmlRpcHandler to also have a vvoid SetCapabilities(XElement element) so handlers can specify what capabilities they support - updated the WLW manifest to have a thiner capability set (e.g. no category support) so handlers can light up what they support - updated the XmlRpcHandlers to add what capabilities they support. there'a room for imporoving (adding/removing) specified capabilities here so the WLW only shows features for what's supported - added WLW support for tags so a tags input can be used in place of the categories input in the WLW UI --HG-- branch : dev --- .../Orchard.Tests.Modules.csproj | 1 + .../XmlRpc/Controllers/HomeControllerTests.cs | 2 + .../Controllers/LiveWriterControllerTests.cs | 60 ++++++++ src/Orchard.Web/Core/Orchard.Core.csproj | 1 + .../Controllers/LiveWriterController.cs | 29 +++- src/Orchard.Web/Core/XmlRpc/IXmlRpcDriver.cs | 5 + src/Orchard.Web/Core/XmlRpc/IXmlRpcHandler.cs | 5 +- src/Orchard.Web/Core/XmlRpc/XmlRpcContext.cs | 2 + .../Controllers/BlogController.cs | 68 +-------- .../RemoteBlogPublishingController.cs | 59 ++++++++ .../Extensions/UrlHelperExtensions.cs | 4 +- .../Orchard.Blogs/Orchard.Blogs.csproj | 1 + .../Modules/Orchard.Blogs/Routes.cs | 19 +-- .../Orchard.Blogs/Services/XmlRpcHandler.cs | 45 +++--- .../Orchard.Media/Services/XmlRpcHandler.cs | 6 + .../Modules/Orchard.Tags/Orchard.Tags.csproj | 1 + .../Orchard.Tags/Services/XmlRpcHandler.cs | 134 ++++++++++++++++++ 17 files changed, 331 insertions(+), 111 deletions(-) create mode 100644 src/Orchard.Tests.Modules/XmlRpc/Controllers/LiveWriterControllerTests.cs create mode 100644 src/Orchard.Web/Core/XmlRpc/IXmlRpcDriver.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Blogs/Controllers/RemoteBlogPublishingController.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Tags/Services/XmlRpcHandler.cs diff --git a/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj b/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj index 8512c3825..c17b0c3dc 100644 --- a/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj +++ b/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj @@ -147,6 +147,7 @@ + diff --git a/src/Orchard.Tests.Modules/XmlRpc/Controllers/HomeControllerTests.cs b/src/Orchard.Tests.Modules/XmlRpc/Controllers/HomeControllerTests.cs index ff7e41af4..d9bb4b10c 100644 --- a/src/Orchard.Tests.Modules/XmlRpc/Controllers/HomeControllerTests.cs +++ b/src/Orchard.Tests.Modules/XmlRpc/Controllers/HomeControllerTests.cs @@ -37,6 +37,8 @@ namespace Orchard.Tests.Modules.XmlRpc.Controllers { } public class StubHandler : IXmlRpcHandler { + public void SetCapabilities(XElement element) {} + public void Process(XmlRpcContext context) { ProcessCalls++; context.Response = new XRpcMethodResponse(); diff --git a/src/Orchard.Tests.Modules/XmlRpc/Controllers/LiveWriterControllerTests.cs b/src/Orchard.Tests.Modules/XmlRpc/Controllers/LiveWriterControllerTests.cs new file mode 100644 index 000000000..2df1e0831 --- /dev/null +++ b/src/Orchard.Tests.Modules/XmlRpc/Controllers/LiveWriterControllerTests.cs @@ -0,0 +1,60 @@ +using System; +using System.Web.Mvc; +using System.Xml.Linq; +using Autofac; +using NUnit.Framework; +using Orchard.Core.XmlRpc; +using Orchard.Core.XmlRpc.Controllers; +using Orchard.Core.XmlRpc.Models; +using Orchard.Core.XmlRpc.Services; + +namespace Orchard.Tests.Modules.XmlRpc.Controllers { + [TestFixture] + public class LiveWriterControllerTests { + [Test] + public void HandlersShouldSetCapabilitiesForManifest() { + var thing = new StubHandler(); + var thingToo = new StubTooHandler(); + + var builder = new ContainerBuilder(); + builder.RegisterType(); + builder.RegisterType().As>(); + builder.RegisterType().As>(); + builder.RegisterInstance(thing).As(); + builder.RegisterInstance(thingToo).As(); + + var container = builder.Build(); + + var controller = container.Resolve(); + var result = controller.Manifest() as ContentResult; + Assert.That(result, Is.Not.Null); + Assert.That(result.Content, Is.StringContaining("No")); + Assert.That(result.Content, Is.StringContaining("Yes")); + Assert.That(result.Content, Is.StringContaining("Maybe")); + + } + + public class StubHandler : IXmlRpcHandler { + public void SetCapabilities(XElement options) { + const string manifestUri = "http://schemas.microsoft.com/wlw/manifest/weblog"; + options.SetElementValue(XName.Get("supportsGetTags", manifestUri), "No"); + options.SetElementValue(XName.Get("keywordsAsTags", manifestUri), "Yes"); + } + + public void Process(XmlRpcContext context) { } + + public int ProcessCalls { get; set; } + } + + public class StubTooHandler : IXmlRpcHandler { + public void SetCapabilities(XElement options) { + const string manifestUri = "http://schemas.microsoft.com/wlw/manifest/weblog"; + options.SetElementValue(XName.Get("supportsKeywords", manifestUri), "Maybe"); + } + + public void Process(XmlRpcContext context) { } + + public int ProcessCalls { get; set; } + } + } +} \ 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 663a745fd..5d9ba62af 100644 --- a/src/Orchard.Web/Core/Orchard.Core.csproj +++ b/src/Orchard.Web/Core/Orchard.Core.csproj @@ -245,6 +245,7 @@ + diff --git a/src/Orchard.Web/Core/XmlRpc/Controllers/LiveWriterController.cs b/src/Orchard.Web/Core/XmlRpc/Controllers/LiveWriterController.cs index c498ae11b..54501817a 100644 --- a/src/Orchard.Web/Core/XmlRpc/Controllers/LiveWriterController.cs +++ b/src/Orchard.Web/Core/XmlRpc/Controllers/LiveWriterController.cs @@ -1,33 +1,52 @@ -using System.Web; +using System; +using System.Collections.Generic; +using System.Web; using System.Web.Mvc; using System.Xml.Linq; using Orchard.Logging; namespace Orchard.Core.XmlRpc.Controllers { public class LiveWriterController : Controller { + private readonly IEnumerable _xmlRpcHandlers; private const string ManifestUri = "http://schemas.microsoft.com/wlw/manifest/weblog"; - public LiveWriterController() { + public LiveWriterController(IEnumerable xmlRpcHandlers) { + _xmlRpcHandlers = xmlRpcHandlers; Logger = NullLogger.Instance; } protected ILogger Logger { get; set; } - + [NoCache] public ActionResult Manifest() { Logger.Debug("Manifest requested"); var options = new XElement( XName.Get("options", ManifestUri), new XElement(XName.Get("clientType", ManifestUri), "Metaweblog"), - new XElement(XName.Get("supportsSlug", ManifestUri), "Yes")); + new XElement(XName.Get("supportsKeywords", ManifestUri), "No"), + new XElement(XName.Get("supportsCategories", ManifestUri), "No"), + new XElement(XName.Get("supportsFileUpload", ManifestUri), "No")); + + foreach (var handler in _xmlRpcHandlers) + handler.SetCapabilities(options); var doc = new XDocument(new XElement( XName.Get("manifest", ManifestUri), options)); - Response.Cache.SetCacheability(HttpCacheability.NoCache); return Content(doc.ToString(), "text/xml"); } + + public class NoCache : ActionFilterAttribute { + public override void OnResultExecuting(ResultExecutingContext filterContext) { + filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1)); + filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false); + filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches); + filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache); + filterContext.HttpContext.Response.Cache.SetNoStore(); + base.OnResultExecuting(filterContext); + } + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Core/XmlRpc/IXmlRpcDriver.cs b/src/Orchard.Web/Core/XmlRpc/IXmlRpcDriver.cs new file mode 100644 index 000000000..949fa104b --- /dev/null +++ b/src/Orchard.Web/Core/XmlRpc/IXmlRpcDriver.cs @@ -0,0 +1,5 @@ +namespace Orchard.Core.XmlRpc { + public interface IXmlRpcDriver { + void Process(int id); + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/XmlRpc/IXmlRpcHandler.cs b/src/Orchard.Web/Core/XmlRpc/IXmlRpcHandler.cs index 9efee82fb..d87203632 100644 --- a/src/Orchard.Web/Core/XmlRpc/IXmlRpcHandler.cs +++ b/src/Orchard.Web/Core/XmlRpc/IXmlRpcHandler.cs @@ -1,5 +1,8 @@ -namespace Orchard.Core.XmlRpc { +using System.Xml.Linq; + +namespace Orchard.Core.XmlRpc { public interface IXmlRpcHandler : IDependency { + void SetCapabilities(XElement element); void Process(XmlRpcContext context); } } \ No newline at end of file diff --git a/src/Orchard.Web/Core/XmlRpc/XmlRpcContext.cs b/src/Orchard.Web/Core/XmlRpc/XmlRpcContext.cs index a8d8d52ed..114a81f11 100644 --- a/src/Orchard.Web/Core/XmlRpc/XmlRpcContext.cs +++ b/src/Orchard.Web/Core/XmlRpc/XmlRpcContext.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Web; using System.Web.Mvc; using Orchard.Core.XmlRpc.Models; @@ -8,5 +9,6 @@ namespace Orchard.Core.XmlRpc { public HttpContextBase HttpContext { get; set; } public XRpcMethodCall Request { get; set; } public XRpcMethodResponse Response { get; set; } + public ICollection _drivers = new List(); } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogController.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogController.cs index 71f9e8843..eae373f93 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogController.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogController.cs @@ -1,10 +1,6 @@ using System.Linq; -using System.Web; using System.Web.Mvc; -using System.Web.Routing; -using System.Xml.Linq; using Orchard.Blogs.Extensions; -using Orchard.Blogs.Models; using Orchard.Blogs.Routing; using Orchard.Blogs.Services; using Orchard.Core.Feeds; @@ -21,22 +17,19 @@ namespace Orchard.Blogs.Controllers { private readonly IBlogPostService _blogPostService; private readonly IBlogSlugConstraint _blogSlugConstraint; private readonly IFeedManager _feedManager; - private readonly RouteCollection _routeCollection; public BlogController( IOrchardServices services, IBlogService blogService, IBlogPostService blogPostService, IBlogSlugConstraint blogSlugConstraint, - IFeedManager feedManager, - RouteCollection routeCollection, + IFeedManager feedManager, IShapeFactory shapeFactory) { _services = services; _blogService = blogService; _blogPostService = blogPostService; _blogSlugConstraint = blogSlugConstraint; _feedManager = feedManager; - _routeCollection = routeCollection; Logger = NullLogger.Instance; Shape = shapeFactory; } @@ -79,64 +72,5 @@ namespace Orchard.Blogs.Controllers { return View(blog); } - - public ActionResult LiveWriterManifest(string blogSlug) { - Logger.Debug("Live Writer Manifest requested"); - - BlogPart blogPart = _blogService.Get(blogSlug); - - if (blogPart == null) - return HttpNotFound(); - - const string manifestUri = "http://schemas.microsoft.com/wlw/manifest/weblog"; - - var options = new XElement( - XName.Get("options", manifestUri), - new XElement(XName.Get("clientType", manifestUri), "Metaweblog"), - new XElement(XName.Get("supportsSlug", manifestUri), "Yes"), - new XElement(XName.Get("supportsKeywords", manifestUri), "Yes")); - - - var doc = new XDocument(new XElement( - XName.Get("manifest", manifestUri), - options)); - - Response.Cache.SetCacheability(HttpCacheability.NoCache); - return Content(doc.ToString(), "text/xml"); - } - - public ActionResult Rsd(string blogSlug) { - Logger.Debug("RSD requested"); - - BlogPart blogPart = _blogService.Get(blogSlug); - - if (blogPart == null) - return HttpNotFound(); - - const string manifestUri = "http://archipelago.phrasewise.com/rsd"; - - var urlHelper = new UrlHelper(ControllerContext.RequestContext, _routeCollection); - var url = urlHelper.Action("", "", new { Area = "XmlRpc" }); - - var options = new XElement( - XName.Get("service", manifestUri), - new XElement(XName.Get("engineName", manifestUri), "Orchard CMS"), - new XElement(XName.Get("engineLink", manifestUri), "http://orchardproject.net"), - new XElement(XName.Get("homePageLink", manifestUri), "http://orchardproject.net"), - new XElement(XName.Get("apis", manifestUri), - new XElement(XName.Get("api", manifestUri), - new XAttribute("name", "MetaWeblog"), - new XAttribute("preferred", true), - new XAttribute("apiLink", url), - new XAttribute("blogID", blogPart.Id)))); - - var doc = new XDocument(new XElement( - XName.Get("rsd", manifestUri), - new XAttribute("version", "1.0"), - options)); - - Response.Cache.SetCacheability(HttpCacheability.NoCache); - return Content(doc.ToString(), "text/xml"); - } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/RemoteBlogPublishingController.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/RemoteBlogPublishingController.cs new file mode 100644 index 000000000..322440bb7 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/RemoteBlogPublishingController.cs @@ -0,0 +1,59 @@ +using System.Collections.Generic; +using System.Web; +using System.Web.Mvc; +using System.Web.Routing; +using System.Xml.Linq; +using Orchard.Blogs.Models; +using Orchard.Blogs.Services; +using Orchard.Environment.Extensions; +using Orchard.Logging; + +namespace Orchard.Blogs.Controllers { + [OrchardFeature("Orchard.Blogs.RemotePublishing")] + public class RemoteBlogPublishingController : Controller { + private readonly IBlogService _blogService; + private readonly RouteCollection _routeCollection; + + public RemoteBlogPublishingController(IOrchardServices services, IBlogService blogService, RouteCollection routeCollection) { + _blogService = blogService; + _routeCollection = routeCollection; + Logger = NullLogger.Instance; + } + + protected ILogger Logger { get; set; } + + public ActionResult Rsd(string blogSlug) { + Logger.Debug("RSD requested"); + + BlogPart blogPart = _blogService.Get(blogSlug); + + if (blogPart == null) + return HttpNotFound(); + + const string manifestUri = "http://archipelago.phrasewise.com/rsd"; + + var urlHelper = new UrlHelper(ControllerContext.RequestContext, _routeCollection); + var url = urlHelper.Action("", "", new { Area = "XmlRpc" }); + + var options = new XElement( + XName.Get("service", manifestUri), + new XElement(XName.Get("engineName", manifestUri), "Orchard CMS"), + new XElement(XName.Get("engineLink", manifestUri), "http://orchardproject.net"), + new XElement(XName.Get("homePageLink", manifestUri), "http://orchardproject.net"), + new XElement(XName.Get("apis", manifestUri), + new XElement(XName.Get("api", manifestUri), + new XAttribute("name", "MetaWeblog"), + new XAttribute("preferred", true), + new XAttribute("apiLink", url), + new XAttribute("blogID", blogPart.Id)))); + + var doc = new XDocument(new XElement( + XName.Get("rsd", manifestUri), + new XAttribute("version", "1.0"), + options)); + + Response.Cache.SetCacheability(HttpCacheability.NoCache); + return Content(doc.ToString(), "text/xml"); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Extensions/UrlHelperExtensions.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Extensions/UrlHelperExtensions.cs index 19e81e140..96577cefa 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Extensions/UrlHelperExtensions.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Extensions/UrlHelperExtensions.cs @@ -20,11 +20,11 @@ namespace Orchard.Blogs.Extensions { } public static string BlogLiveWriterManifest(this UrlHelper urlHelper, BlogPart blogPart) { - return urlHelper.AbsoluteAction(() => urlHelper.Action("LiveWriterManifest", "Blog", new { blogSlug = blogPart.As().Path, area = "Orchard.Blogs" })); + return urlHelper.AbsoluteAction(() => urlHelper.Action("Manifest", "LiveWriter", new { area = "XmlRpc" })); } public static string BlogRsd(this UrlHelper urlHelper, BlogPart blogPart) { - return urlHelper.AbsoluteAction(() => urlHelper.Action("Rsd", "Blog", new { blogSlug = blogPart.As().Path, area = "Orchard.Blogs" })); + return urlHelper.AbsoluteAction(() => urlHelper.Action("Rsd", "RemoteBlogPublishing", new { blogSlug = blogPart.As().Path, area = "Orchard.Blogs" })); } public static string BlogArchiveYear(this UrlHelper urlHelper, BlogPart blogPart, int year) { diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Orchard.Blogs.csproj b/src/Orchard.Web/Modules/Orchard.Blogs/Orchard.Blogs.csproj index 6ba4015e9..2983c45c4 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Orchard.Blogs.csproj +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Orchard.Blogs.csproj @@ -67,6 +67,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Routes.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Routes.cs index 6f8b3b879..e6407fdcc 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Routes.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Routes.cs @@ -202,30 +202,13 @@ namespace Orchard.Blogs { }, new MvcRouteHandler()) }, - new RouteDescriptor { - Priority = 11, - Route = new Route( - "{blogSlug}/wlwmanifest.xml", - new RouteValueDictionary { - {"area", "Orchard.Blogs"}, - {"controller", "Blog"}, - {"action", "LiveWriterManifest"} - }, - new RouteValueDictionary { - {"blogSlug", _blogSlugConstraint} - }, - new RouteValueDictionary { - {"area", "Orchard.Blogs"} - }, - new MvcRouteHandler()) - }, new RouteDescriptor { Priority = 11, Route = new Route( "{blogSlug}/rsd", new RouteValueDictionary { {"area", "Orchard.Blogs"}, - {"controller", "Blog"}, + {"controller", "RemoteBlogPublishing"}, {"action", "Rsd"} }, new RouteValueDictionary { diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs index a079dc202..756af11dd 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs @@ -1,7 +1,9 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Web.Mvc; using System.Web.Routing; +using System.Xml.Linq; using JetBrains.Annotations; using Orchard.Blogs.Models; using Orchard.ContentManagement; @@ -44,6 +46,11 @@ namespace Orchard.Blogs.Services { public ILogger Logger { get; set; } + public void SetCapabilities(XElement options) { + const string manifestUri = "http://schemas.microsoft.com/wlw/manifest/weblog"; + options.SetElementValue(XName.Get("supportsSlug", manifestUri), "Yes"); + } + public void Process(XmlRpcContext context) { var urlHelper = new UrlHelper(context.ControllerContext.RequestContext, _routeCollection); @@ -72,7 +79,8 @@ namespace Orchard.Blogs.Services { 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)); + Convert.ToBoolean(context.Request.Params[4].Value), + context._drivers); context.Response = new XRpcMethodResponse().Add(result); } @@ -92,7 +100,8 @@ namespace Orchard.Blogs.Services { 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)); + Convert.ToBoolean(context.Request.Params[4].Value), + context._drivers); context.Response = new XRpcMethodResponse().Add(result); } @@ -102,7 +111,8 @@ namespace Orchard.Blogs.Services { Convert.ToString(context.Request.Params[1].Value), Convert.ToString(context.Request.Params[2].Value), Convert.ToString(context.Request.Params[3].Value), - Convert.ToBoolean(context.Request.Params[4].Value)); + Convert.ToBoolean(context.Request.Params[4].Value), + context._drivers); context.Response = new XRpcMethodResponse().Add(result); } } @@ -152,7 +162,8 @@ namespace Orchard.Blogs.Services { string userName, string password, XRpcStruct content, - bool publish) { + bool publish, + IEnumerable drivers) { var user = _membershipService.ValidateUser(userName, password); _authorizationService.CheckAccess(Permissions.EditBlogPost, user, null); @@ -191,6 +202,9 @@ namespace Orchard.Blogs.Services { if (publish) _blogPostService.Publish(blogPost); + foreach (var driver in drivers) + driver.Process(blogPost.Id); + return blogPost.Id; } @@ -210,12 +224,7 @@ namespace Orchard.Blogs.Services { return CreateBlogStruct(blogPost, urlHelper); } - private bool MetaWeblogEditPost( - int postId, - string userName, - string password, - XRpcStruct content, - bool publish) { + private bool MetaWeblogEditPost(int postId, string userName, string password, XRpcStruct content, bool publish, ICollection drivers) { var user = _membershipService.ValidateUser(userName, password); _authorizationService.CheckAccess(StandardPermissions.AccessFrontEnd, user, null); @@ -233,19 +242,16 @@ namespace Orchard.Blogs.Services { blogPost.Slug = slug; blogPost.Text = description; - if (publish) { + if (publish) _blogPostService.Publish(blogPost); - } + + foreach (var driver in drivers) + driver.Process(blogPost.Id); return true; } - private bool MetaWeblogDeletePost( - string appkey, - string postId, - string userName, - string password, - bool publish) { + private bool MetaWeblogDeletePost(string appkey, string postId, string userName, string password, bool publish, ICollection drivers) { var user = _membershipService.ValidateUser(userName, password); _authorizationService.CheckAccess(StandardPermissions.AccessFrontEnd, user, null); @@ -253,6 +259,9 @@ namespace Orchard.Blogs.Services { if (blogPost == null) throw new ArgumentException(); + foreach (var driver in drivers) + driver.Process(blogPost.Id); + _blogPostService.Delete(blogPost); return true; } diff --git a/src/Orchard.Web/Modules/Orchard.Media/Services/XmlRpcHandler.cs b/src/Orchard.Web/Modules/Orchard.Media/Services/XmlRpcHandler.cs index d6c72a73a..cdeb7974f 100644 --- a/src/Orchard.Web/Modules/Orchard.Media/Services/XmlRpcHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Media/Services/XmlRpcHandler.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Web; +using System.Xml.Linq; using JetBrains.Annotations; using Orchard.Core.XmlRpc; using Orchard.Core.XmlRpc.Models; @@ -18,6 +19,11 @@ namespace Orchard.Media.Services { _authorizationService = authorizationService; } + public void SetCapabilities(XElement options) { + const string manifestUri = "http://schemas.microsoft.com/wlw/manifest/weblog"; + options.SetElementValue(XName.Get("supportsFileUpload", manifestUri), "Yes"); + } + public void Process(XmlRpcContext context) { var uriBuilder = new UriBuilder(context.HttpContext.Request.ToUrlString()) { Path = context.HttpContext.Request.ApplicationPath, diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Orchard.Tags.csproj b/src/Orchard.Web/Modules/Orchard.Tags/Orchard.Tags.csproj index a58353f55..dc5e821d7 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Orchard.Tags.csproj +++ b/src/Orchard.Web/Modules/Orchard.Tags/Orchard.Tags.csproj @@ -72,6 +72,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Services/XmlRpcHandler.cs b/src/Orchard.Web/Modules/Orchard.Tags/Services/XmlRpcHandler.cs new file mode 100644 index 000000000..b44d6b3f8 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Tags/Services/XmlRpcHandler.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using Orchard.ContentManagement; +using Orchard.Core.XmlRpc; +using Orchard.Core.XmlRpc.Models; +using Orchard.Security; +using Orchard.Tags.Helpers; + +namespace Orchard.Tags.Services { + public class XmlRpcHandler : IXmlRpcHandler { + private readonly IMembershipService _membershipService; + private readonly IAuthorizationService _authorizationService; + private readonly IContentManager _contentManager; + private readonly ITagService _tagService; + private readonly IOrchardServices _orchardServices; + private IEnumerable _tags; + + public XmlRpcHandler( + IMembershipService membershipService, + IAuthorizationService authorizationService, + IContentManager contentManager, + ITagService tagService, + IOrchardServices orchardServices) { + _membershipService = membershipService; + _authorizationService = authorizationService; + _contentManager = contentManager; + _tagService = tagService; + _orchardServices = orchardServices; + } + + public void SetCapabilities(XElement options) { + const string manifestUri = "http://schemas.microsoft.com/wlw/manifest/weblog"; + options.SetElementValue(XName.Get("supportsKeywords", manifestUri), "Yes"); + options.SetElementValue(XName.Get("supportsGetTags", manifestUri), "Yes"); + options.SetElementValue(XName.Get("keywordsAsTags", manifestUri), "Yes"); + } + + public void Process(XmlRpcContext context) { + switch (context.Request.MethodName) { + case "wp.getTags": + var tags = MetaWeblogGetTags( + Convert.ToString(context.Request.Params[0].Value), + Convert.ToString(context.Request.Params[1].Value), + Convert.ToString(context.Request.Params[2].Value)); + context.Response = new XRpcMethodResponse().Add(tags); + break; + case "metaWeblog.newPost": + MetaWeblogUpdateTags( + 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": + MetaWeblogUpdateTags( + 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 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 XRpcArray MetaWeblogGetTags(string appKey, string userName, string password) { + var user = _membershipService.ValidateUser(userName, password); + _authorizationService.CheckAccess(StandardPermissions.AccessFrontEnd, user, null); + + var array = new XRpcArray(); + foreach (var tag in _tagService.GetTags()) { + var thisTag = tag; + array.Add(new XRpcStruct() + .Set("tag_id", thisTag.TagName) + .Set("name", thisTag.TagName)); + // nyi - not yet implemented + //.Set("count", "") + //.Set("slug", "") + //.Set("html_url", "") + //.Set("rss_url", "")); + } + + return array; + } + + private void MetaWeblogUpdateTags(int contentItemId, string appKey, string userName, string password, XRpcStruct content, bool publish, ICollection drivers) { + var user = _membershipService.ValidateUser(userName, password); + _authorizationService.CheckAccess(Permissions.ApplyTag, user, null); + + var rawTags = content.Optional("mt_keywords"); + if (string.IsNullOrWhiteSpace(rawTags)) + return; + + var driver = new XmlRpcDriver(id => { + var contentItem = _contentManager.Get(id); + if (contentItem == null) + return; + + _orchardServices.WorkContext.CurrentUser = user; + _tagService.UpdateTagsForContentItem(id, _tags); + }); + + _tags = TagHelpers.ParseCommaSeparatedTagNames(rawTags); + if (contentItemId > 0) + driver.Process(contentItemId); + else + drivers.Add(driver); + } + + public class XmlRpcDriver : IXmlRpcDriver { + private readonly Action _process; + + public XmlRpcDriver(Action process) { + _process = process; + } + + public void Process(int id) { + _process(id); + } + } + } +} \ No newline at end of file