From 429889b36ee14648595c5326fb586c54ce5fa232 Mon Sep 17 00:00:00 2001 From: MatteoPiovanelli-Laser Date: Thu, 20 Oct 2016 21:24:47 +0200 Subject: [PATCH 1/6] [Fixes #5811] Adding a VaryByRequestCookies property to the CacheSettingsPart Fixes #5811 --- .../Orchard.OutputCache/Controllers/AdminController.cs | 2 ++ .../Orchard.OutputCache/Filters/OutputCacheFilter.cs | 6 ++++++ .../Modules/Orchard.OutputCache/Models/CacheSettings.cs | 2 ++ .../Orchard.OutputCache/Models/CacheSettingsPart.cs | 5 +++++ .../Orchard.OutputCache/ViewModels/IndexViewModel.cs | 1 + .../Modules/Orchard.OutputCache/Views/Admin/Index.cshtml | 8 +++++++- 6 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Controllers/AdminController.cs index f8a042706..a2798425d 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Controllers/AdminController.cs @@ -89,6 +89,7 @@ namespace Orchard.OutputCache.Controllers { DefaultMaxAge = settings.DefaultMaxAge, VaryByQueryStringParameters = settings.VaryByQueryStringParameters, VaryByRequestHeaders = settings.VaryByRequestHeaders, + VaryByRequestCookies = settings.VaryByRequestCookies, IgnoredUrls = settings.IgnoredUrls, IgnoreNoCache = settings.IgnoreNoCache, VaryByCulture = settings.VaryByCulture, @@ -116,6 +117,7 @@ namespace Orchard.OutputCache.Controllers { settings.DefaultMaxAge = model.DefaultMaxAge; settings.VaryByQueryStringParameters = model.VaryByQueryStringParameters; settings.VaryByRequestHeaders = model.VaryByRequestHeaders; + settings.VaryByRequestCookies = model.VaryByRequestCookies; settings.IgnoredUrls = model.IgnoredUrls; settings.IgnoreNoCache = model.IgnoreNoCache; settings.VaryByCulture = model.VaryByCulture; diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs index 548012e6b..4e0bc04a3 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs @@ -397,6 +397,12 @@ namespace Orchard.OutputCache.Filters { result["HEADER:" + varyByRequestHeader] = requestHeaders[varyByRequestHeader]; } + // Vary by configured cookies. + var requestCookies = filterContext.RequestContext.HttpContext.Request.Cookies; + foreach (var varyByRequestCookies in CacheSettings.VaryByRequestCookies) { + if (requestCookies[varyByRequestCookies] != null) + result["COOKIE:" + varyByRequestCookies] = requestCookies[varyByRequestCookies].Value; + } // Vary by request culture if configured. if (CacheSettings.VaryByCulture) { diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettings.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettings.cs index 62075c24d..7797d7382 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettings.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettings.cs @@ -14,6 +14,7 @@ namespace Orchard.OutputCache.Models { VaryByQueryStringParameters = String.IsNullOrWhiteSpace(part.VaryByQueryStringParameters) ? null : part.VaryByQueryStringParameters.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToArray(); VaryByRequestHeaders = String.IsNullOrWhiteSpace(part.VaryByRequestHeaders) ? new HashSet() : new HashSet(part.VaryByRequestHeaders.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToArray()); VaryByRequestHeaders.Add("HOST"); // Always vary by host name/tenant. + VaryByRequestCookies = String.IsNullOrWhiteSpace(part.VaryByRequestCookies) ? new HashSet() : new HashSet(part.VaryByRequestCookies.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToArray()); IgnoredUrls = String.IsNullOrWhiteSpace(part.IgnoredUrls) ? null : part.IgnoredUrls.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToArray(); IgnoreNoCache = part.IgnoreNoCache; VaryByCulture = part.VaryByCulture; @@ -27,6 +28,7 @@ namespace Orchard.OutputCache.Models { public int DefaultMaxAge { get; private set; } public IEnumerable VaryByQueryStringParameters { get; private set; } public ISet VaryByRequestHeaders { get; private set; } + public ISet VaryByRequestCookies { get; private set; } public IEnumerable IgnoredUrls { get; private set; } public bool IgnoreNoCache { get; private set; } public bool VaryByCulture { get; private set; } diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettingsPart.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettingsPart.cs index b11eb3fae..69e8441fd 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettingsPart.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettingsPart.cs @@ -44,6 +44,11 @@ namespace Orchard.OutputCache.Models { } } + public string VaryByRequestCookies { + get { return this.Retrieve(x => x.VaryByRequestCookies); } + set { this.Store(x => x.VaryByRequestCookies, value); } + } + public string IgnoredUrls { get { return this.Retrieve(x => x.IgnoredUrls); } set { this.Store(x => x.IgnoredUrls, value); } diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/ViewModels/IndexViewModel.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/ViewModels/IndexViewModel.cs index 1cda10ada..b79ff5509 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/ViewModels/IndexViewModel.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/ViewModels/IndexViewModel.cs @@ -11,6 +11,7 @@ namespace Orchard.OutputCache.ViewModels { [Range(0, Int32.MaxValue), Required] public int DefaultMaxAge { get; set; } public string VaryByQueryStringParameters { get; set; } public string VaryByRequestHeaders { get; set; } + public string VaryByRequestCookies { get; set; } public string IgnoredUrls { get; set; } public bool IgnoreNoCache { get; set; } public bool VaryByCulture { get; set; } diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.OutputCache/Views/Admin/Index.cshtml index 960b43bb4..9750acb7e 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Views/Admin/Index.cshtml @@ -43,7 +43,13 @@ @Html.TextBoxFor(m => m.VaryByRequestHeaders, new { @class = "text medium" }) @T("When defined, using comma separated values, sets caching to vary by the specified request headers.") - + +
+ + @Html.TextBoxFor(m => m.VaryByRequestCookies, new { @class = "text medium" }) + @T("When defined, using comma separated values, sets caching to vary via specified cookie string parameters") +
+
@Html.TextAreaFor(m => m.IgnoredUrls, new { @class = "text medium" }) From 30312ad6b0280d91aec09838d7a57a867291adb8 Mon Sep 17 00:00:00 2001 From: Matthew Harris Date: Thu, 20 Oct 2016 20:25:33 +0100 Subject: [PATCH 2/6] [Fixes #7326] Orchard.Widgets - Fix typo in logger (#7327) --- src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs index 7535cf1a7..20b570714 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs @@ -59,7 +59,7 @@ namespace Orchard.Widgets.Filters { foreach (var widgetPart in widgetParts) { var commonPart = widgetPart.As(); if (commonPart == null || commonPart.Container == null) { - Logger.Warning("The widget '{0}' is has no assigned layer or the layer does not exist.", widgetPart.Title); + Logger.Warning("The widget '{0}' has no assigned layer or the layer does not exist.", widgetPart.Title); continue; } From 9be38010b0fe26d845b5afd2f29c5691b5457937 Mon Sep 17 00:00:00 2001 From: Matthew Harris Date: Thu, 20 Oct 2016 20:26:23 +0100 Subject: [PATCH 3/6] [Fixes #7071] Orchard.Users - Users last login time is not correct (#7325) Fixes #7071 --- .../Modules/Orchard.Users/Views/Admin/Index.cshtml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Index.cshtml index fef515c51..5cac51030 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Index.cshtml @@ -87,10 +87,14 @@ } - @Display(New.DateTimeRelative(dateTimeUtc: entry.User.CreatedUtc)) + @if (entry.User.CreatedUtc != null) { + @Display(New.DateTimeRelative(dateTimeUtc: entry.User.CreatedUtc)) + } - @Display(New.DateTimeRelative(dateTimeUtc: entry.User.LastLoginUtc)) + @if (entry.User.LastLoginUtc != null) { + @Display(New.DateTimeRelative(dateTimeUtc: entry.User.LastLoginUtc)) + } userIndex++; From 4a5ed9790acd7316c80a8240ac33ef5e31295fe3 Mon Sep 17 00:00:00 2001 From: Matthew Harris Date: Thu, 20 Oct 2016 20:30:47 +0100 Subject: [PATCH 4/6] [Fixes #7251, Fixes #1659] Orchard.Setup - Blog recipe doesn't create widgets correctly (#7324) Fixes #7251, Fixes #1659 --- .../Commands/BlogWidgetCommands.cs | 165 ++++++++++++++++++ .../Orchard.Blogs/Orchard.Blogs.csproj | 1 + .../Orchard.Blogs/Services/BlogService.cs | 2 +- .../Orchard.Setup/Recipes/blog.recipe.xml | 8 +- .../Commands/TagsWidgetCommands.cs | 116 ++++++++++++ .../Modules/Orchard.Tags/Orchard.Tags.csproj | 2 + 6 files changed, 289 insertions(+), 5 deletions(-) create mode 100644 src/Orchard.Web/Modules/Orchard.Blogs/Commands/BlogWidgetCommands.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Tags/Commands/TagsWidgetCommands.cs diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Commands/BlogWidgetCommands.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Commands/BlogWidgetCommands.cs new file mode 100644 index 000000000..af390fd45 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Commands/BlogWidgetCommands.cs @@ -0,0 +1,165 @@ +using System; +using System.Linq; +using Orchard.Blogs.Models; +using Orchard.Blogs.Services; +using Orchard.Commands; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Aspects; +using Orchard.Core.Common.Models; +using Orchard.Security; +using Orchard.Settings; +using Orchard.Widgets.Models; +using Orchard.Widgets.Services; + +namespace Orchard.Blogs.Commands { + public class BlogWidgetCommands : DefaultOrchardCommandHandler { + private readonly IWidgetsService _widgetsService; + private readonly IBlogService _blogService; + private readonly ISiteService _siteService; + private readonly IMembershipService _membershipService; + private readonly IContentManager _contentManager; + + private BlogPart blog; + + public BlogWidgetCommands( + IWidgetsService widgetsService, + IBlogService blogService, + ISiteService siteService, + IMembershipService membershipService, + IContentManager contentManager) { + _widgetsService = widgetsService; + _blogService = blogService; + _siteService = siteService; + _membershipService = membershipService; + _contentManager = contentManager; + + RenderTitle = true; + } + + [OrchardSwitch] + public string Title { get; set; } + + [OrchardSwitch] + public string Name { get; set; } + + [OrchardSwitch] + public bool RenderTitle { get; set; } + + [OrchardSwitch] + public string Zone { get; set; } + + [OrchardSwitch] + public string Position { get; set; } + + [OrchardSwitch] + public string Layer { get; set; } + + [OrchardSwitch] + public string Identity { get; set; } + + [OrchardSwitch] + public string Owner { get; set; } + + [OrchardSwitch] + public string BlogPath { get; set; } + + [OrchardSwitch] + public int BlogId { get; set; } + + [OrchardSwitch] + public string Count { get; set; } + + [CommandName("blog widget create recentblogposts")] + [CommandHelp("blog widget create recentblogposts /Title: /Name:<name> /Zone:<zone> /Position:<position> /Layer:<layer> (/BlogId:<id> | /BlogPath:<path>) [/Identity:<identity>] [/RenderTitle:true|false] [/Owner:<owner>] [/Count:<count>]\r\n\t" + "Creates a new widget")] + [OrchardSwitches("Title,Name,Zone,Position,Layer,BlogId,BlogPath,Identity,Owner,RenderTitle,Count")] + public void CreateRecentBlogPostsWidget() { + var type = "RecentBlogPosts"; + + var widget = CreateStandardWidget(type); + if (widget == null) { + return; + } + + widget.As<RecentBlogPostsPart>().BlogId = blog.Id; + + // Setting count to 0 means all posts. It's an optional parameter and defaults to 5. + if (!string.IsNullOrWhiteSpace(Count)) { + int CountAsNumber = 0; + if (Int32.TryParse(Count, out CountAsNumber)) { + widget.As<RecentBlogPostsPart>().Count = CountAsNumber; + } + } + + _contentManager.Publish(widget.ContentItem); + Context.Output.WriteLine(T("{0} widget created successfully.", type).Text); + } + + [CommandName("blog widget create blogarchives")] + [CommandHelp("blog widget create blogarchives /Title:<title> /Name:<name> /Zone:<zone> /Position:<position> /Layer:<layer> (/BlogId:<id> | /BlogPath:<path>) [/Identity:<identity>] [/RenderTitle:true|false] [/Owner:<owner>]\r\n\t" + "Creates a new widget")] + [OrchardSwitches("Title,Name,Zone,Position,Layer,BlogId,BlogPath,Identity,Owner,RenderTitle")] + public void CreateBlogArchivesWidget() { + var type = "BlogArchives"; + + var widget = CreateStandardWidget(type); + if (widget == null) { + return; + } + + widget.As<BlogArchivesPart>().BlogId = blog.Id; + + _contentManager.Publish(widget.ContentItem); + Context.Output.WriteLine(T("{0} widget created successfully.", type).Text); + } + + private WidgetPart CreateStandardWidget(string type) { + var widgetTypeNames = _widgetsService.GetWidgetTypeNames().ToList(); + if (!widgetTypeNames.Contains(type)) { + Context.Output.WriteLine(T("Creating widget failed: type {0} was not found. Supported widget types are: {1}.", + type, + string.Join(" ", widgetTypeNames))); + return null; + } + + var layer = GetLayer(Layer); + if (layer == null) { + Context.Output.WriteLine(T("Creating {0} widget failed: layer {1} was not found.", type, Layer)); + return null; + } + + blog = GetBlog(BlogId, BlogPath); + if (blog == null) { + Context.Output.WriteLine(T("Creating {0} widget failed: blog was not found.", type)); + return null; + } + + var widget = _widgetsService.CreateWidget(layer.ContentItem.Id, type, T(Title).Text, Position, Zone); + + if (!String.IsNullOrWhiteSpace(Name)) { + widget.Name = Name.Trim(); + } + + widget.RenderTitle = RenderTitle; + + if (String.IsNullOrEmpty(Owner)) { + Owner = _siteService.GetSiteSettings().SuperUser; + } + var owner = _membershipService.GetUser(Owner); + widget.As<ICommonPart>().Owner = owner; + + if (widget.Has<IdentityPart>() && !String.IsNullOrEmpty(Identity)) { + widget.As<IdentityPart>().Identifier = Identity; + } + + return widget; + } + + private LayerPart GetLayer(string layer) { + var layers = _widgetsService.GetLayers(); + return layers.FirstOrDefault(layerPart => String.Equals(layerPart.Name, layer, StringComparison.OrdinalIgnoreCase)); + } + + private BlogPart GetBlog(int blogId, string blogPath) { + return _contentManager.Get<BlogPart>(blogId) ?? _blogService.Get(blogPath); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Orchard.Blogs.csproj b/src/Orchard.Web/Modules/Orchard.Blogs/Orchard.Blogs.csproj index 25f36dc12..d4b202396 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Orchard.Blogs.csproj +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Orchard.Blogs.csproj @@ -93,6 +93,7 @@ </ItemGroup> <ItemGroup> <Compile Include="AdminMenu.cs" /> + <Compile Include="Commands\BlogWidgetCommands.cs" /> <Compile Include="Controllers\RemoteBlogPublishingController.cs" /> <Compile Include="Drivers\BlogArchivesPartDriver.cs" /> <Compile Include="Drivers\RemoteBlogPublishingDriver.cs" /> diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Services/BlogService.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Services/BlogService.cs index ed3a16a34..b431dabca 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Services/BlogService.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Services/BlogService.cs @@ -17,7 +17,7 @@ namespace Orchard.Blogs.Services { private readonly ShellSettings _shellSettings; private readonly IShellDescriptorManager _shellDescriptorManager; private readonly HashSet<int> _processedBlogParts = new HashSet<int>(); - IPathResolutionService _pathResolutionService; + private readonly IPathResolutionService _pathResolutionService; public BlogService( IContentManager contentManager, diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Recipes/blog.recipe.xml b/src/Orchard.Web/Modules/Orchard.Setup/Recipes/blog.recipe.xml index 49e8befb6..e5a5d69ed 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Recipes/blog.recipe.xml +++ b/src/Orchard.Web/Modules/Orchard.Setup/Recipes/blog.recipe.xml @@ -56,13 +56,13 @@ layer create Anonymous /LayerRule:"not authenticated" /Description:"The widgets in this layer are displayed when the user is anonymous" layer create Disabled /LayerRule:"false" /Description:"The widgets in this layer are never displayed" layer create TheHomepage /LayerRule:"url '~/'" /Description:"The widgets in this layer are displayed on the home page" - widget create RecentBlogPosts /Title:"Recent Blog Posts" /Zone:"AsideSecond" /Position:"5" /Layer:"TheHomepage" /Identity:"RecentBlogPosts1" - widget create BlogArchives /Title:"Blog Archives" /Zone:"AsideSecond" /Position:"6" /Layer:"TheHomepage" /Identity:"BlogArchives1" - widget create TagCloud /Title:"Blog Post Tags" /Zone:"AsideSecond" /Position:"7" /Layer:"TheHomepage" /Identity:"TagCloud1" + blog create /Title:"Blog" /Homepage:true /Description:"This is your Orchard Blog." + blog widget create RecentBlogPosts /Title:"Recent Blog Posts" /Zone:"AsideSecond" /Position:"5" /Layer:"TheHomepage" /Identity:"RecentBlogPosts1" /BlogPath:"" + blog widget create BlogArchives /Title:"Blog Archives" /Zone:"AsideSecond" /Position:"60" /Layer:"TheHomepage" /Identity:"BlogArchives1" /BlogPath:"" + tags widget create TagCloud /Title:"Blog Post Tags" /Zone:"AsideSecond" /Position:"70" /Layer:"TheHomepage" /Identity:"TagCloud1" /Slug:"/" site setting set baseurl theme activate "The Theme Machine" menu create /MenuName:"Main Menu" - blog create /Title:"Blog" /Homepage:true /Description:"This is your Orchard Blog." menuitem create /MenuPosition:"0" /MenuText:"Home" /Url:"~/" /MenuName:"Main Menu" widget create MenuWidget /Title:"Main Menu" /RenderTitle:false /Zone:"Navigation" /Position:"1" /Layer:"Default" /Identity:"MenuWidget1" /MenuName:"Main Menu" </Command> diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Commands/TagsWidgetCommands.cs b/src/Orchard.Web/Modules/Orchard.Tags/Commands/TagsWidgetCommands.cs new file mode 100644 index 000000000..0e9b79662 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Tags/Commands/TagsWidgetCommands.cs @@ -0,0 +1,116 @@ +using System; +using System.Linq; +using Orchard.Commands; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Aspects; +using Orchard.Core.Common.Models; +using Orchard.Security; +using Orchard.Settings; +using Orchard.Tags.Models; +using Orchard.Widgets.Models; +using Orchard.Widgets.Services; + +namespace Orchard.Tags.Commands { + public class TagWidgetCommands : DefaultOrchardCommandHandler { + private readonly IWidgetsService _widgetsService; + private readonly ISiteService _siteService; + private readonly IMembershipService _membershipService; + private readonly IContentManager _contentManager; + + public TagWidgetCommands( + IWidgetsService widgetsService, + ISiteService siteService, + IMembershipService membershipService, + IContentManager contentManager) { + _widgetsService = widgetsService; + _siteService = siteService; + _membershipService = membershipService; + _contentManager = contentManager; + + RenderTitle = true; + } + + [OrchardSwitch] + public string Title { get; set; } + + [OrchardSwitch] + public string Name { get; set; } + + [OrchardSwitch] + public bool RenderTitle { get; set; } + + [OrchardSwitch] + public string Zone { get; set; } + + [OrchardSwitch] + public string Position { get; set; } + + [OrchardSwitch] + public string Layer { get; set; } + + [OrchardSwitch] + public string Identity { get; set; } + + [OrchardSwitch] + public string Owner { get; set; } + + [OrchardSwitch] + public string Slug { get; set; } + + [OrchardSwitch] + public string Buckets { get; set; } + + [CommandName("tags widget create tagcloud")] + [CommandHelp("tags widget create tagcloud /Title:<title> /Name:<name> /Zone:<zone> /Position:<position> /Layer:<layer> [/Identity:<identity>] [/RenderTitle:true|false] [/Owner:<owner>] [/Slug:<slug>] [/Buckets:<number>]\r\n\t" + "Creates a new widget")] + [OrchardSwitches("Title,Name,Zone,Position,Layer,Buckets,Identity,Owner,RenderTitle,Slug")] + public void CreateTagsCloudWidget() { + var type = "TagCloud"; + + var layer = GetLayer(Layer); + if (layer == null) { + Context.Output.WriteLine(T("Creating {0} widget failed: layer {1} was not found.", type, Layer)); + return; + } + + var widget = _widgetsService.CreateWidget(layer.ContentItem.Id, type, T(Title).Text, Position, Zone); + + if (!String.IsNullOrWhiteSpace(Name)) { + widget.Name = Name.Trim(); + } + + widget.RenderTitle = RenderTitle; + + if (String.IsNullOrEmpty(Owner)) { + Owner = _siteService.GetSiteSettings().SuperUser; + } + var owner = _membershipService.GetUser(Owner); + widget.As<ICommonPart>().Owner = owner; + + if (widget.Has<IdentityPart>() && !String.IsNullOrEmpty(Identity)) { + widget.As<IdentityPart>().Identifier = Identity; + } + + if (widget == null) { + return; + } + + widget.As<TagCloudPart>().Slug = Slug; + + // It's an optional parameter and defaults to 5. + if (!string.IsNullOrWhiteSpace(Buckets)) { + int BucketsAsNumber = 0; + if (Int32.TryParse(Buckets, out BucketsAsNumber)) { + widget.As<TagCloudPart>().Buckets = BucketsAsNumber; + } + } + + _contentManager.Publish(widget.ContentItem); + Context.Output.WriteLine(T("{0} widget created successfully.", type).Text); + } + + private LayerPart GetLayer(string layer) { + var layers = _widgetsService.GetLayers(); + return layers.FirstOrDefault(layerPart => String.Equals(layerPart.Name, layer, StringComparison.OrdinalIgnoreCase)); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Orchard.Tags.csproj b/src/Orchard.Web/Modules/Orchard.Tags/Orchard.Tags.csproj index 77aef27b5..c78f9ef38 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Orchard.Tags.csproj +++ b/src/Orchard.Web/Modules/Orchard.Tags/Orchard.Tags.csproj @@ -99,6 +99,7 @@ </ItemGroup> <ItemGroup> <Compile Include="AdminMenu.cs" /> + <Compile Include="Commands\TagsWidgetCommands.cs" /> <Compile Include="Controllers\AdminController.cs" /> <Compile Include="Drivers\TagCloudDriver.cs" /> <Compile Include="Feeds\TagFeedQuery.cs" /> @@ -195,6 +196,7 @@ <ItemGroup> <Content Include="packages.config" /> </ItemGroup> + <ItemGroup /> <PropertyGroup> <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> From fef68ad7ae390fa23b760200713d74a90192cf72 Mon Sep 17 00:00:00 2001 From: Matthew Harris <rtpharry@hotmail.com> Date: Thu, 20 Oct 2016 20:33:55 +0100 Subject: [PATCH 5/6] Orchard.Roles GetRoles should defer execution (#7320) Fixes #7278 --- src/Orchard.Web/Modules/Orchard.Roles/Services/RoleService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Orchard.Web/Modules/Orchard.Roles/Services/RoleService.cs b/src/Orchard.Web/Modules/Orchard.Roles/Services/RoleService.cs index a7c3ce0f7..3240669e0 100644 --- a/src/Orchard.Web/Modules/Orchard.Roles/Services/RoleService.cs +++ b/src/Orchard.Web/Modules/Orchard.Roles/Services/RoleService.cs @@ -46,7 +46,7 @@ namespace Orchard.Roles.Services { public IEnumerable<RoleRecord> GetRoles() { var roles = from role in _roleRepository.Table select role; - return roles.ToList(); + return roles; } public RoleRecord GetRole(int id) { From 7a16cf527cb97cde450226cf70751e1f81ea7972 Mon Sep 17 00:00:00 2001 From: Matthew Harris <rtpharry@hotmail.com> Date: Fri, 21 Oct 2016 14:58:28 +0100 Subject: [PATCH 6/6] [Fixes #7258] Orchard.Core - Tabbed groupby breaks priority (#7336) Fixes #7258 --- src/Orchard.Web/Core/Shapes/CoreShapes.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Orchard.Web/Core/Shapes/CoreShapes.cs b/src/Orchard.Web/Core/Shapes/CoreShapes.cs index 98722594c..c9b6d5aa6 100644 --- a/src/Orchard.Web/Core/Shapes/CoreShapes.cs +++ b/src/Orchard.Web/Core/Shapes/CoreShapes.cs @@ -283,7 +283,7 @@ namespace Orchard.Core.Shapes { [Shape] public void ContentZone(dynamic Display, dynamic Shape, TextWriter Output) { var unordered = ((IEnumerable<dynamic>)Shape).ToArray(); - var tabbed = unordered.GroupBy(x => (string)x.Metadata.Tab); + var tabbed = unordered.GroupBy(x => (string)x.Metadata.Tab ?? ""); if (tabbed.Count() > 1) { foreach (var tab in tabbed) {