From 746d3d54c25932de039e27feb8f56bc689a33430 Mon Sep 17 00:00:00 2001 From: Thierry Fleury Date: Tue, 18 Aug 2015 12:46:09 +0200 Subject: [PATCH 01/25] Fixes 5614 : ContentPickerField and LayoutPart throws argument null exception. --- .../Modules/Orchard.ContentPicker/Fields/ContentPickerField.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Fields/ContentPickerField.cs b/src/Orchard.Web/Modules/Orchard.ContentPicker/Fields/ContentPickerField.cs index b08c95247..9d037c02e 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Fields/ContentPickerField.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Fields/ContentPickerField.cs @@ -17,7 +17,7 @@ namespace Orchard.ContentPicker.Fields { public IEnumerable ContentItems { get { - return _contentItems.Value; + return _contentItems.Value ?? new ContentItem[0]; } } From 9980633ac3228c97939cb99100499567b6d2b544 Mon Sep 17 00:00:00 2001 From: Thierry Fleury Date: Thu, 20 Aug 2015 23:57:38 +0200 Subject: [PATCH 02/25] Use Enumerable.Empty --- .../Modules/Orchard.ContentPicker/Fields/ContentPickerField.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Fields/ContentPickerField.cs b/src/Orchard.Web/Modules/Orchard.ContentPicker/Fields/ContentPickerField.cs index 9d037c02e..8b7c15194 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Fields/ContentPickerField.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Fields/ContentPickerField.cs @@ -17,7 +17,7 @@ namespace Orchard.ContentPicker.Fields { public IEnumerable ContentItems { get { - return _contentItems.Value ?? new ContentItem[0]; + return _contentItems.Value ?? Enumerable.Empty(); } } From cfc1dc23791c60427382f70696417a74785c5273 Mon Sep 17 00:00:00 2001 From: Gustavo Tandeciarz Date: Fri, 21 Aug 2015 20:08:41 -0400 Subject: [PATCH 03/25] Enables gulp watch of Assets.json Will restart the watch task when Assets.json is changed. --- src/Gulpfile.js | 54 ++++++++++++++++++++++++++++++++++-------------- src/Package.json | 4 +++- 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/Gulpfile.js b/src/Gulpfile.js index 05b62a89e..69a24ed64 100644 --- a/src/Gulpfile.js +++ b/src/Gulpfile.js @@ -13,7 +13,8 @@ var glob = require("glob"), uglify = require("gulp-uglify"), rename = require("gulp-rename"), concat = require("gulp-concat"), - header = require("gulp-header"); + header = require("gulp-header"), + fs = require("fs"); /* ** GULP TASKS @@ -37,32 +38,53 @@ gulp.task("rebuild", function () { return merge(assetGroupTasks); }); -// Continuous watch (each asset group is built whenever one of its inputs changes). + +// Set "Watchers" as sub-processes in order to restart the task when Assets.json changes. gulp.task("watch", function () { - var pathWin32 = require("path"); - getAssetGroups().forEach(function (assetGroup) { - var watchPaths = assetGroup.inputPaths.concat(assetGroup.watchPaths); - gulp.watch(watchPaths, function (event) { - var isConcat = path.basename(assetGroup.outputFileName, path.extname(assetGroup.outputFileName)) !== "@"; - if (isConcat) - console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group with output '" + assetGroup.outputPath + "'."); - else - console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group."); - var doRebuild = true; - var task = createAssetGroupTask(assetGroup, doRebuild); + var watchers; + function restart() { + if (watchers) { + watchers.forEach(function (w) { + w.remove(); + w.end(); + }); + } + watchers = []; + // Continuous watch (each asset group is built whenever one of its inputs changes). + getAssetGroups().forEach(function (assetGroup) { + var watchPaths = assetGroup.inputPaths.concat(assetGroup.watchPaths); + var watcher = gulp.watch(watchPaths, function (event) { + var isConcat = path.basename(assetGroup.outputFileName, path.extname(assetGroup.outputFileName)) !== "@"; + if (isConcat) + console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group with output '" + assetGroup.outputPath + "'."); + else + console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group."); + var doRebuild = true; + var task = createAssetGroupTask(assetGroup, doRebuild); + }); + watchers.push(watcher); }); + } + var p; + if (p) { p.exit(); } + p = gulp.watch("Orchard.Web/{Core,Modules,Themes}/*/Assets.json", function (event) { + console.log("Asset file '" + event.path + "' was " + event.type + ", resetting asset watchers."); + restart(); }); + restart(); }); + /* ** ASSET GROUPS */ - function getAssetGroups() { - var assetManifestPaths = glob.sync("Orchard.Web/{Core,Modules,Themes}/*/Assets.json"); + var assetManifestPaths = glob.sync("Orchard.Web/{Core,Modules,Themes}/*/Assets.json", {}); var assetGroups = []; assetManifestPaths.forEach(function (assetManifestPath) { - var assetManifest = require("./" + assetManifestPath); + var file = './' + assetManifestPath; + var json = fs.readFileSync(file, 'utf8'); + assetManifest = eval(json); assetManifest.forEach(function (assetGroup) { resolveAssetGroupPaths(assetGroup, assetManifestPath); assetGroups.push(assetGroup); diff --git a/src/Package.json b/src/Package.json index 96a154825..a46100b18 100644 --- a/src/Package.json +++ b/src/Package.json @@ -15,7 +15,9 @@ "gulp-uglify": "^1.2.0", "gulp-rename": "^1.2.2", "gulp-concat": "^2.5.2", - "gulp-header": "^1.2.2" + "gulp-header": "^1.2.2", + "gulp-util": "^3.0.6", + "fs": "^0.0.2" }, "dependencies": { } } From bbcdd67b95ca0247df064516e06be9caed72e3fe Mon Sep 17 00:00:00 2001 From: Gustavo Tandeciarz Date: Fri, 21 Aug 2015 20:15:51 -0400 Subject: [PATCH 04/25] Cleanup gulp-util was previously used during development and is no longer required. --- src/Package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Package.json b/src/Package.json index a46100b18..f096237f7 100644 --- a/src/Package.json +++ b/src/Package.json @@ -16,7 +16,6 @@ "gulp-rename": "^1.2.2", "gulp-concat": "^2.5.2", "gulp-header": "^1.2.2", - "gulp-util": "^3.0.6", "fs": "^0.0.2" }, "dependencies": { } From f5772334e163c470029593db8da34d2ec41511b3 Mon Sep 17 00:00:00 2001 From: Thierry Fleury Date: Thu, 3 Sep 2015 10:05:02 +0200 Subject: [PATCH 05/25] Fixes #5735 : ContentType name encoding in Lists --- .../Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml b/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml index 10a69f805..2bc7f83ec 100644 --- a/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml @@ -5,13 +5,13 @@ }

- @Html.ActionLink(T("{0} Properties", (string)Model.ContainerDisplayName).ToString(), "Edit", new { Area = "Contents", Id = (int)Model.ContainerId, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl }) + @Html.ActionLink(T("{0} Properties", Html.Raw((string)Model.ContainerDisplayName)).Text, "Edit", new { Area = "Contents", Id = (int)Model.ContainerId, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl })

@if (itemContentTypes.Any()) { foreach (var contentType in itemContentTypes) { - @Html.ActionLink(T("New {0}", contentType.DisplayName).ToString(), "Create", "Admin", new { area = "Contents", id = contentType.Name, containerId }, new { @class = "button primaryAction create-content" }) + @Html.ActionLink(T("New {0}", Html.Raw(contentType.DisplayName)).Text, "Create", "Admin", new { area = "Contents", id = contentType.Name, containerId }, new { @class = "button primaryAction create-content" }) } } else { From 97bb52bbddc92d52d7eb198da45a055e24da35a6 Mon Sep 17 00:00:00 2001 From: Thierry Fleury Date: Fri, 4 Sep 2015 15:05:25 +0200 Subject: [PATCH 06/25] Add LinkExtensions Allows using IHtmlString as linkText --- src/Orchard/Mvc/Html/LinkExtensions.cs | 144 +++++++++++++++++++++++++ src/Orchard/Orchard.Framework.csproj | 1 + 2 files changed, 145 insertions(+) create mode 100644 src/Orchard/Mvc/Html/LinkExtensions.cs diff --git a/src/Orchard/Mvc/Html/LinkExtensions.cs b/src/Orchard/Mvc/Html/LinkExtensions.cs new file mode 100644 index 000000000..34db0c758 --- /dev/null +++ b/src/Orchard/Mvc/Html/LinkExtensions.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Web; +using System.Web.Mvc; +using System.Web.Routing; +using System.Web.WebPages; + +namespace Orchard.Mvc.Html { + public static class LinkExtensions { + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName) { + return ActionLink(htmlHelper, linkText, actionName, null /* controllerName */, new RouteValueDictionary(), new RouteValueDictionary()); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, object routeValues) { + return ActionLink(htmlHelper, linkText, actionName, null /* controllerName */, ObjectToDictionary(routeValues), new RouteValueDictionary()); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, object routeValues, object htmlAttributes) { + return ActionLink(htmlHelper, linkText, actionName, null /* controllerName */, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, RouteValueDictionary routeValues) { + return ActionLink(htmlHelper, linkText, actionName, null /* controllerName */, routeValues, new RouteValueDictionary()); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + return ActionLink(htmlHelper, linkText, actionName, null /* controllerName */, routeValues, htmlAttributes); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, string controllerName) { + return ActionLink(htmlHelper, linkText, actionName, controllerName, new RouteValueDictionary(), new RouteValueDictionary()); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, string controllerName, object routeValues, object htmlAttributes) { + return ActionLink(htmlHelper, linkText, actionName, controllerName, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + if (String.IsNullOrEmpty(linkText.ToString())) { + throw new ArgumentException("Argument must be a non empty string", "linkText"); + } + return MvcHtmlString.Create(GenerateLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, null /* routeName */, actionName, controllerName, routeValues, htmlAttributes)); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, object routeValues, object htmlAttributes) { + return ActionLink(htmlHelper, linkText, actionName, controllerName, protocol, hostName, fragment, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + if (String.IsNullOrEmpty(linkText.ToString())) { + throw new ArgumentException("Argument must be a non empty string", "linkText"); + } + return MvcHtmlString.Create(GenerateLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, null /* routeName */, actionName, controllerName, protocol, hostName, fragment, routeValues, htmlAttributes)); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, object routeValues) { + return RouteLink(htmlHelper, linkText, ObjectToDictionary(routeValues)); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, RouteValueDictionary routeValues) { + return RouteLink(htmlHelper, linkText, routeValues, new RouteValueDictionary()); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName) { + return RouteLink(htmlHelper, linkText, routeName, (object)null /* routeValues */); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, object routeValues) { + return RouteLink(htmlHelper, linkText, routeName, ObjectToDictionary(routeValues)); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, RouteValueDictionary routeValues) { + return RouteLink(htmlHelper, linkText, routeName, routeValues, new RouteValueDictionary()); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, object routeValues, object htmlAttributes) { + return RouteLink(htmlHelper, linkText, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + return RouteLink(htmlHelper, linkText, null /* routeName */, routeValues, htmlAttributes); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, object routeValues, object htmlAttributes) { + return RouteLink(htmlHelper, linkText, routeName, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + if (String.IsNullOrEmpty(linkText.ToString())) { + throw new ArgumentException("Argument must be a non empty string", "linkText"); + } + return MvcHtmlString.Create(GenerateRouteLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, routeName, routeValues, htmlAttributes)); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, string protocol, string hostName, string fragment, object routeValues, object htmlAttributes) { + return RouteLink(htmlHelper, linkText, routeName, protocol, hostName, fragment, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + if (String.IsNullOrEmpty(linkText.ToString())) { + throw new ArgumentException("Argument must be a non empty string", "linkText"); + } + return MvcHtmlString.Create(GenerateRouteLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, routeName, protocol, hostName, fragment, routeValues, htmlAttributes)); + } + + public static string GenerateLink(RequestContext requestContext, RouteCollection routeCollection, IHtmlString linkText, string routeName, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + return GenerateLink(requestContext, routeCollection, linkText, routeName, actionName, controllerName, null /* protocol */, null /* hostName */, null /* fragment */, routeValues, htmlAttributes); + } + + public static string GenerateLink(RequestContext requestContext, RouteCollection routeCollection, IHtmlString linkText, string routeName, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + return GenerateLinkInternal(requestContext, routeCollection, linkText, routeName, actionName, controllerName, protocol, hostName, fragment, routeValues, htmlAttributes, true /* includeImplicitMvcValues */); + } + + public static string GenerateRouteLink(RequestContext requestContext, RouteCollection routeCollection, IHtmlString linkText, string routeName, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + return GenerateRouteLink(requestContext, routeCollection, linkText, routeName, null /* protocol */, null /* hostName */, null /* fragment */, routeValues, htmlAttributes); + } + + public static string GenerateRouteLink(RequestContext requestContext, RouteCollection routeCollection, IHtmlString linkText, string routeName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + return GenerateLinkInternal(requestContext, routeCollection, linkText, routeName, null /* actionName */, null /* controllerName */, protocol, hostName, fragment, routeValues, htmlAttributes, false /* includeImplicitMvcValues */); + } + private static string GenerateLinkInternal(RequestContext requestContext, RouteCollection routeCollection, IHtmlString linkText, string routeName, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary htmlAttributes, bool includeImplicitMvcValues) { + string url = UrlHelper.GenerateUrl(routeName, actionName, controllerName, protocol, hostName, fragment, routeValues, routeCollection, requestContext, includeImplicitMvcValues); + TagBuilder tagBuilder = new TagBuilder("a") { + InnerHtml = linkText.ToString() + }; + tagBuilder.MergeAttributes(htmlAttributes); + tagBuilder.MergeAttribute("href", url); + return tagBuilder.ToString(TagRenderMode.Normal); + } + + private static RouteValueDictionary ObjectToDictionary(object value) { + RouteValueDictionary dictionary = new RouteValueDictionary(); + + if (value != null) { + foreach (var prop in value.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { + dictionary.Add(prop.Name, prop.GetValue(value)); + } + } + + return dictionary; + } + } +} diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index ee62487ba..eba605d31 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -150,6 +150,7 @@ + From 894e90f485bd7c024e19152154d75e51c8883c83 Mon Sep 17 00:00:00 2001 From: Thierry Fleury Date: Fri, 4 Sep 2015 15:08:30 +0200 Subject: [PATCH 07/25] Use new ActionLink extension method. --- .../Orchard.Lists/Views/Parts.Container.Manage.cshtml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml b/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml index 2bc7f83ec..636dff05e 100644 --- a/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml @@ -5,17 +5,17 @@ }

- @Html.ActionLink(T("{0} Properties", Html.Raw((string)Model.ContainerDisplayName)).Text, "Edit", new { Area = "Contents", Id = (int)Model.ContainerId, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl }) + @Html.ActionLink(T("{0} Properties", (string)Model.ContainerDisplayName), "Edit", new { Area = "Contents", Id = (int)Model.ContainerId, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl })

@if (itemContentTypes.Any()) { foreach (var contentType in itemContentTypes) { - @Html.ActionLink(T("New {0}", Html.Raw(contentType.DisplayName)).Text, "Create", "Admin", new { area = "Contents", id = contentType.Name, containerId }, new { @class = "button primaryAction create-content" }) + @Html.ActionLink(T("New {0}", contentType.DisplayName), "Create", "Admin", new { area = "Contents", id = contentType.Name, containerId }, new { @class = "button primaryAction create-content" }) } } else { - @Html.ActionLink(T("New Content").ToString(), "Create", "Admin", new { area = "Contents", containerId }, new { @class = "button primaryAction create-content" }) + @Html.ActionLink(T("New Content"), "Create", "Admin", new { area = "Contents", containerId }, new { @class = "button primaryAction create-content" }) } @T("Choose Items")
From 9b91b1b2609439bb50dfc0321e72e5f39a95022f Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Fri, 4 Sep 2015 13:20:08 -0700 Subject: [PATCH 08/25] Removing unnecessary resolution --- src/Orchard/Mvc/MvcModule.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Orchard/Mvc/MvcModule.cs b/src/Orchard/Mvc/MvcModule.cs index 2da05b755..4125c4706 100644 --- a/src/Orchard/Mvc/MvcModule.cs +++ b/src/Orchard/Mvc/MvcModule.cs @@ -52,7 +52,6 @@ namespace Orchard.Mvc { var baseUrl = new Func(() => siteService.GetSiteSettings().BaseUrl); var httpContextBase = new HttpContextPlaceholder(baseUrl); - context.Resolve().CreateWorkContextScope(httpContextBase); return httpContextBase; } From 39fb266221046363943593dbe168598a2e2f16b9 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Fri, 4 Sep 2015 15:59:24 -0700 Subject: [PATCH 09/25] Skipping DateTime tests until the right solution is found c.f. #5702 --- src/Orchard.Tests/Localization/DateTimePartsTests.cs | 2 +- src/Orchard.Tests/Localization/DefaultDateFormatterTests.cs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Orchard.Tests/Localization/DateTimePartsTests.cs b/src/Orchard.Tests/Localization/DateTimePartsTests.cs index 4532b0448..77340e45c 100644 --- a/src/Orchard.Tests/Localization/DateTimePartsTests.cs +++ b/src/Orchard.Tests/Localization/DateTimePartsTests.cs @@ -4,7 +4,7 @@ using Orchard.Localization.Models; namespace Orchard.Tests.Localization { - [TestFixture] + [TestFixture(Ignore = true, IgnoreReason = "Long running tests, stable code.")] public class DateTimePartsTests { [Test] diff --git a/src/Orchard.Tests/Localization/DefaultDateFormatterTests.cs b/src/Orchard.Tests/Localization/DefaultDateFormatterTests.cs index 8a4226c84..0e9534109 100644 --- a/src/Orchard.Tests/Localization/DefaultDateFormatterTests.cs +++ b/src/Orchard.Tests/Localization/DefaultDateFormatterTests.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; @@ -13,7 +12,7 @@ using Orchard.Localization.Services; namespace Orchard.Tests.Localization { - [TestFixture] + [TestFixture(Ignore = true, IgnoreReason = "Long running tests, stable code.")] public class DefaultDateFormatterTests { [SetUp] From 14482162fd4abec3e3ebc585871e993be54ce359 Mon Sep 17 00:00:00 2001 From: Daniel Stolt Date: Sun, 6 Sep 2015 00:31:15 +0200 Subject: [PATCH 10/25] Marked some tests as long-running. Fixes #5702. --- src/Orchard.Tests/Localization/DateTimePartsTests.cs | 2 +- src/Orchard.Tests/Localization/DefaultDateFormatterTests.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Orchard.Tests/Localization/DateTimePartsTests.cs b/src/Orchard.Tests/Localization/DateTimePartsTests.cs index 77340e45c..6a3ee09e4 100644 --- a/src/Orchard.Tests/Localization/DateTimePartsTests.cs +++ b/src/Orchard.Tests/Localization/DateTimePartsTests.cs @@ -4,7 +4,7 @@ using Orchard.Localization.Models; namespace Orchard.Tests.Localization { - [TestFixture(Ignore = true, IgnoreReason = "Long running tests, stable code.")] + [TestFixture()] public class DateTimePartsTests { [Test] diff --git a/src/Orchard.Tests/Localization/DefaultDateFormatterTests.cs b/src/Orchard.Tests/Localization/DefaultDateFormatterTests.cs index 0e9534109..a2135f09c 100644 --- a/src/Orchard.Tests/Localization/DefaultDateFormatterTests.cs +++ b/src/Orchard.Tests/Localization/DefaultDateFormatterTests.cs @@ -12,7 +12,8 @@ using Orchard.Localization.Services; namespace Orchard.Tests.Localization { - [TestFixture(Ignore = true, IgnoreReason = "Long running tests, stable code.")] + [TestFixture()] + [Category("longrunning")] public class DefaultDateFormatterTests { [SetUp] From a6855171184a28707ac7d5443719cdb2e23b50a0 Mon Sep 17 00:00:00 2001 From: Lombiq Date: Mon, 7 Sep 2015 00:17:57 +0200 Subject: [PATCH 11/25] Normalizing all catch (Exception ex) lines and adding exception fatality check where applicable, fixes #3949 --- src/Orchard.WarmupStarter/Starter.cs | 4 +- .../Navigation/Controllers/AdminController.cs | 5 +++ .../Navigation/Services/NavigationManager.cs | 10 +++++ .../Services/ScheduledTaskExecutor.cs | 4 ++ .../Drivers/SiteSettingsPartDriver.cs | 8 +++- .../Metadata/ContentDefinitionManager.cs | 4 ++ .../Caching/DefaultAsyncTokenProvider.cs | 10 +++-- src/Orchard/Commands/CommandHostAgent.cs | 39 ++++++++++++------- .../Commands/DefaultOrchardCommandHandler.cs | 8 +++- .../Data/Migration/AutomaticDataMigrations.cs | 8 +++- .../Data/Migration/DataMigrationManager.cs | 13 +++++-- .../Data/Migration/Schema/SchemaBuilder.cs | 4 ++ src/Orchard/Data/SessionConfigurationCache.cs | 12 ++++-- src/Orchard/Environment/DefaultOrchardHost.cs | 8 +++- .../Environment/DefaultOrchardShell.cs | 9 ++++- .../Compilers/DefaultExtensionCompiler.cs | 8 +++- .../Extensions/ExtensionManager.cs | 4 ++ .../Extensions/Folders/ExtensionHarvester.cs | 4 ++ src/Orchard/Environment/IAssemblyLoader.cs | 9 ++++- src/Orchard/Environment/IBuildManager.cs | 5 ++- src/Orchard/Environment/IHostLocalRestart.cs | 8 +++- .../Environment/ViewsBackgroundCompilation.cs | 8 +++- src/Orchard/Events/DefaultOrchardEventBus.cs | 4 ++ .../FileSystems/AppData/AppDataFolder.cs | 8 +++- .../DefaultExtensionDependenciesManager.cs | 8 +++- .../Media/FileSystemStorageProvider.cs | 4 ++ .../VirtualPath/DefaultVirtualPathProvider.cs | 15 +++++-- .../Services/DefaultMessageManager.cs | 15 +++++-- src/Orchard/Mvc/MvcModule.cs | 7 +++- src/Orchard/Tasks/BackgroundService.cs | 9 ++++- src/Orchard/Tasks/SweepGenerator.cs | 5 +++ src/Orchard/Time/SiteTimeZoneSelector.cs | 8 +++- .../Admin/Notification/NotificationManager.cs | 8 +++- 33 files changed, 217 insertions(+), 66 deletions(-) diff --git a/src/Orchard.WarmupStarter/Starter.cs b/src/Orchard.WarmupStarter/Starter.cs index ffa1f0763..b0b328da4 100644 --- a/src/Orchard.WarmupStarter/Starter.cs +++ b/src/Orchard.WarmupStarter/Starter.cs @@ -89,9 +89,9 @@ namespace Orchard.WarmupStarter { var result = _initialization(application); _initializationResult = result; } - catch (Exception e) { + catch (Exception ex) { lock (_synLock) { - _error = e; + _error = ex; _previousError = null; } } diff --git a/src/Orchard.Web/Core/Navigation/Controllers/AdminController.cs b/src/Orchard.Web/Core/Navigation/Controllers/AdminController.cs index 659a998db..a0b8087f2 100644 --- a/src/Orchard.Web/Core/Navigation/Controllers/AdminController.cs +++ b/src/Orchard.Web/Core/Navigation/Controllers/AdminController.cs @@ -17,6 +17,7 @@ using Orchard.UI.Navigation; using Orchard.Utility; using System; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Core.Navigation.Controllers { [ValidateInput(false)] @@ -179,6 +180,10 @@ namespace Orchard.Core.Navigation.Controllers { return View(model); } catch (Exception exception) { + if (exception.IsFatal()) { + throw; + } + Logger.Error(T("Creating menu item failed: {0}", exception.Message).Text); Services.Notifier.Error(T("Creating menu item failed: {0}", exception.Message)); return this.RedirectLocal(returnUrl, () => RedirectToAction("Index")); diff --git a/src/Orchard.Web/Core/Navigation/Services/NavigationManager.cs b/src/Orchard.Web/Core/Navigation/Services/NavigationManager.cs index bf7a529ea..a090a1bb2 100644 --- a/src/Orchard.Web/Core/Navigation/Services/NavigationManager.cs +++ b/src/Orchard.Web/Core/Navigation/Services/NavigationManager.cs @@ -11,6 +11,7 @@ using Orchard.Security.Permissions; using Orchard.UI; using Orchard.UI.Navigation; using Orchard.Utility; +using Orchard.Exceptions; namespace Orchard.Core.Navigation.Services { public class NavigationManager : INavigationManager { @@ -152,6 +153,9 @@ namespace Orchard.Core.Navigation.Services { items = builder.Build(); } catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } Logger.Error(ex, "Unexpected error while querying a navigation provider. It was ignored. The menu provided by the provider may not be complete."); } if (items != null) { @@ -170,6 +174,9 @@ namespace Orchard.Core.Navigation.Services { items = builder.Build(); } catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } Logger.Error(ex, "Unexpected error while querying a menu provider. It was ignored. The menu provided by the provider may not be complete."); } if (items != null) { @@ -188,6 +195,9 @@ namespace Orchard.Core.Navigation.Services { imageSets = builder.BuildImageSets(); } catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } Logger.Error(ex, "Unexpected error while querying a navigation provider. It was ignored. The menu provided by the provider may not be complete."); } if (imageSets != null) { diff --git a/src/Orchard.Web/Core/Scheduling/Services/ScheduledTaskExecutor.cs b/src/Orchard.Web/Core/Scheduling/Services/ScheduledTaskExecutor.cs index 8485a9518..d4483aaab 100644 --- a/src/Orchard.Web/Core/Scheduling/Services/ScheduledTaskExecutor.cs +++ b/src/Orchard.Web/Core/Scheduling/Services/ScheduledTaskExecutor.cs @@ -9,6 +9,7 @@ using Orchard.Logging; using Orchard.Services; using Orchard.Tasks; using Orchard.Tasks.Scheduling; +using Orchard.Exceptions; namespace Orchard.Core.Scheduling.Services { [UsedImplicitly] @@ -65,6 +66,9 @@ namespace Orchard.Core.Scheduling.Services { } } catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } Logger.Warning(ex, "Unable to process scheduled task #{0} of type {1}", taskEntry.Id, taskEntry.Action); _transactionManager.Cancel(); } diff --git a/src/Orchard.Web/Core/Settings/Drivers/SiteSettingsPartDriver.cs b/src/Orchard.Web/Core/Settings/Drivers/SiteSettingsPartDriver.cs index 6cba80e53..5591115e5 100644 --- a/src/Orchard.Web/Core/Settings/Drivers/SiteSettingsPartDriver.cs +++ b/src/Orchard.Web/Core/Settings/Drivers/SiteSettingsPartDriver.cs @@ -11,6 +11,7 @@ using Orchard.Logging; using Orchard.Security; using Orchard.Settings; using Orchard.UI.Notify; +using Orchard.Exceptions; namespace Orchard.Core.Settings.Drivers { [UsedImplicitly] @@ -102,9 +103,12 @@ namespace Orchard.Core.Settings.Drivers { using (request.GetResponse() as HttpWebResponse) {} } } - catch (Exception e) { + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } _notifier.Warning(T("The base url you entered could not be requested from current location.")); - Logger.Warning(e, "Could not query base url: {0}", model.Site.BaseUrl); + Logger.Warning(ex, "Could not query base url: {0}", model.Site.BaseUrl); } } } diff --git a/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs b/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs index e434318e1..16c1d1f78 100644 --- a/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs +++ b/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs @@ -9,6 +9,7 @@ using Orchard.ContentManagement.MetaData.Services; using Orchard.Core.Settings.Metadata.Records; using Orchard.Data; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Core.Settings.Metadata { public class ContentDefinitionManager : Component, IContentDefinitionManager { @@ -282,6 +283,9 @@ namespace Orchard.Core.Settings.Metadata { return XElement.Parse(settings); } catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } Logger.Error(ex, "Unable to parse settings xml"); return null; } diff --git a/src/Orchard/Caching/DefaultAsyncTokenProvider.cs b/src/Orchard/Caching/DefaultAsyncTokenProvider.cs index b6769ec82..9f13571c0 100644 --- a/src/Orchard/Caching/DefaultAsyncTokenProvider.cs +++ b/src/Orchard/Caching/DefaultAsyncTokenProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Caching { public class DefaultAsyncTokenProvider : IAsyncTokenProvider { @@ -37,9 +38,12 @@ namespace Orchard.Caching { try { _task(token => _taskTokens.Add(token)); } - catch (Exception e) { - Logger.Error(e, "Error while monitoring extension files. Assuming extensions are not current."); - _taskException = e; + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error(ex, "Error while monitoring extension files. Assuming extensions are not current."); + _taskException = ex; } finally { _isTaskFinished = true; diff --git a/src/Orchard/Commands/CommandHostAgent.cs b/src/Orchard/Commands/CommandHostAgent.cs index 6c7a955aa..04ab5a31a 100644 --- a/src/Orchard/Commands/CommandHostAgent.cs +++ b/src/Orchard/Commands/CommandHostAgent.cs @@ -15,6 +15,7 @@ using Orchard.FileSystems.VirtualPath; using Orchard.Localization; using Orchard.Logging; using Orchard.Tasks; +using Orchard.Exceptions; namespace Orchard.Commands { @@ -94,19 +95,21 @@ namespace Orchard.Commands { return CommandReturnCodes.Ok; } - catch (OrchardCommandHostRetryException e) { + catch (OrchardCommandHostRetryException ex) { // Special "Retry" return code for our host - output.WriteLine(T("{0} (Retrying...)", e.Message)); + output.WriteLine(T("{0} (Retrying...)", ex.Message)); return CommandReturnCodes.Retry; } - catch (Exception e) { - if (e is TargetInvocationException && - e.InnerException != null) { - // If this is an exception coming from reflection and there is an innerexception which is the actual one, redirect - e = e.InnerException; + catch (Exception ex) { + if (ex.IsFatal()) { + throw; } - - OutputException(output, T("Error executing command \"{0}\"", string.Join(" ", args)), e); + if (ex is TargetInvocationException && + ex.InnerException != null) { + // If this is an exception coming from reflection and there is an innerexception which is the actual one, redirect + ex = ex.InnerException; + } + OutputException(output, T("Error executing command \"{0}\"", string.Join(" ", args)), ex); return CommandReturnCodes.Fail; } } @@ -116,13 +119,16 @@ namespace Orchard.Commands { _hostContainer = CreateHostContainer(); return CommandReturnCodes.Ok; } - catch (OrchardCommandHostRetryException e) { + catch (OrchardCommandHostRetryException ex) { // Special "Retry" return code for our host - output.WriteLine(T("{0} (Retrying...)", e.Message)); + output.WriteLine(T("{0} (Retrying...)", ex.Message)); return CommandReturnCodes.Retry; } - catch (Exception e) { - OutputException(output, T("Error starting up Orchard command line host"), e); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + OutputException(output, T("Error starting up Orchard command line host"), ex); return CommandReturnCodes.Fail; } } @@ -135,8 +141,11 @@ namespace Orchard.Commands { } return CommandReturnCodes.Ok; } - catch (Exception e) { - OutputException(output, T("Error shutting down Orchard command line host"), e); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + OutputException(output, T("Error shutting down Orchard command line host"), ex); return CommandReturnCodes.Fail; } } diff --git a/src/Orchard/Commands/DefaultOrchardCommandHandler.cs b/src/Orchard/Commands/DefaultOrchardCommandHandler.cs index a5e8a3d89..7936ddef1 100644 --- a/src/Orchard/Commands/DefaultOrchardCommandHandler.cs +++ b/src/Orchard/Commands/DefaultOrchardCommandHandler.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using Orchard.Localization; +using Orchard.Exceptions; namespace Orchard.Commands { public abstract class DefaultOrchardCommandHandler : ICommandHandler { @@ -41,12 +42,15 @@ namespace Orchard.Commands { object value = Convert.ChangeType(commandSwitch.Value, propertyInfo.PropertyType); propertyInfo.SetValue(this, value, null/*index*/); } - catch(Exception e) { + catch(Exception ex) { + if (ex.IsFatal()) { + throw; + } string message = T("Error converting value \"{0}\" to \"{1}\" for switch \"{2}\"", LocalizedString.TextOrDefault(commandSwitch.Value, T("(empty)")), propertyInfo.PropertyType.FullName, commandSwitch.Key).Text; - throw new InvalidOperationException(message, e); + throw new InvalidOperationException(message, ex); } } diff --git a/src/Orchard/Data/Migration/AutomaticDataMigrations.cs b/src/Orchard/Data/Migration/AutomaticDataMigrations.cs index 2a6e1ed49..9f3abddd9 100644 --- a/src/Orchard/Data/Migration/AutomaticDataMigrations.cs +++ b/src/Orchard/Data/Migration/AutomaticDataMigrations.cs @@ -3,6 +3,7 @@ using System.Linq; using Orchard.Environment; using Orchard.Environment.Features; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Data.Migration { /// @@ -41,8 +42,11 @@ namespace Orchard.Data.Migration { try { _dataMigrationManager.Update(feature); } - catch (Exception e) { - Logger.Error("Could not run migrations automatically on " + feature, e); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error("Could not run migrations automatically on " + feature, ex); } } } diff --git a/src/Orchard/Data/Migration/DataMigrationManager.cs b/src/Orchard/Data/Migration/DataMigrationManager.cs index 1ef6e33d7..02c6204f0 100644 --- a/src/Orchard/Data/Migration/DataMigrationManager.cs +++ b/src/Orchard/Data/Migration/DataMigrationManager.cs @@ -9,6 +9,7 @@ using Orchard.Data.Migration.Schema; using Orchard.Environment.Extensions; using Orchard.Localization; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Data.Migration { /// @@ -123,6 +124,9 @@ namespace Orchard.Data.Migration { current = (int)lookupTable[current].Invoke(migration, new object[0]); } catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } Logger.Error(ex, "An unexpected error occurred while applying migration on {0} from version {1}.", feature, current); throw; } @@ -139,10 +143,13 @@ namespace Orchard.Data.Migration { dataMigrationRecord.Version = current; } } - catch (Exception e) { - Logger.Error(e, "Error while running migration version {0} for {1}.", current, feature); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error(ex, "Error while running migration version {0} for {1}.", current, feature); _transactionManager.Cancel(); - throw new OrchardException(T("Error while running migration version {0} for {1}.", current, feature), e); + throw new OrchardException(T("Error while running migration version {0} for {1}.", current, feature), ex); } } diff --git a/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs b/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs index de5291a61..15e149f1e 100644 --- a/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs +++ b/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs @@ -1,6 +1,7 @@ using System; using Orchard.Data.Migration.Interpreters; using Orchard.Localization; +using Orchard.Exceptions; namespace Orchard.Data.Migration.Schema { public class SchemaBuilder { @@ -65,6 +66,9 @@ namespace Orchard.Data.Migration.Schema { Run(sqlStatmentCommand); return this; } catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } throw new OrchardException(T("An unexpected error occured while executing the SQL statement: {0}", sql), ex); // Add the sql to the nested exception information } } diff --git a/src/Orchard/Data/SessionConfigurationCache.cs b/src/Orchard/Data/SessionConfigurationCache.cs index 037f80801..30bae0547 100644 --- a/src/Orchard/Data/SessionConfigurationCache.cs +++ b/src/Orchard/Data/SessionConfigurationCache.cs @@ -11,6 +11,7 @@ using Orchard.Environment.ShellBuilders.Models; using Orchard.FileSystems.AppData; using Orchard.Logging; using Orchard.Utility; +using Orchard.Exceptions; namespace Orchard.Data { public class SessionConfigurationCache : ISessionConfigurationCache { @@ -80,11 +81,11 @@ namespace Orchard.Data { formatter.Serialize(stream, cache.Configuration); } } - catch (SerializationException e) { + catch (SerializationException ex) { //Note: This can happen when multiple processes/AppDomains try to save // the cached configuration at the same time. Only one concurrent // writer will win, and it's harmless for the other ones to fail. - for (Exception scan = e; scan != null; scan = scan.InnerException) + for (Exception scan = ex; scan != null; scan = scan.InnerException) Logger.Warning("Error storing new NHibernate cache configuration: {0}", scan.Message); } } @@ -118,8 +119,11 @@ namespace Orchard.Data { }; } } - catch (Exception e) { - for (var scan = e; scan != null; scan = scan.InnerException) + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + for (var scan = ex; scan != null; scan = scan.InnerException) Logger.Warning("Error reading the cached NHibernate configuration: {0}", scan.Message); Logger.Information("A new one will be re-generated."); return null; diff --git a/src/Orchard/Environment/DefaultOrchardHost.cs b/src/Orchard/Environment/DefaultOrchardHost.cs index 977515317..c3d9fa782 100644 --- a/src/Orchard/Environment/DefaultOrchardHost.cs +++ b/src/Orchard/Environment/DefaultOrchardHost.cs @@ -13,6 +13,7 @@ using Orchard.Environment.Descriptor.Models; using Orchard.Localization; using Orchard.Logging; using Orchard.Utility.Extensions; +using Orchard.Exceptions; namespace Orchard.Environment { // All the event handlers that DefaultOrchardHost implements have to be declared in OrchardStarter @@ -140,8 +141,11 @@ namespace Orchard.Environment { var context = CreateShellContext(settings); ActivateShell(context); } - catch (Exception e) { - Logger.Error(e, "A tenant could not be started: " + settings.Name); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error(ex, "A tenant could not be started: " + settings.Name); } while (_processingEngine.AreTasksPending()) { Logger.Debug("Processing pending task after activate Shell"); diff --git a/src/Orchard/Environment/DefaultOrchardShell.cs b/src/Orchard/Environment/DefaultOrchardShell.cs index a679dec17..c4f42b786 100644 --- a/src/Orchard/Environment/DefaultOrchardShell.cs +++ b/src/Orchard/Environment/DefaultOrchardShell.cs @@ -13,6 +13,7 @@ using Orchard.Tasks; using Orchard.UI; using Orchard.WebApi.Routes; using Owin; +using Orchard.Exceptions; using IModelBinderProvider = Orchard.Mvc.ModelBinders.IModelBinderProvider; namespace Orchard.Environment { @@ -102,8 +103,12 @@ namespace Orchard.Environment { try { action(); } - catch(Exception e) { - Logger.Error(e, "An unexcepted error occured while terminating the Shell"); + catch(Exception ex) { + if (ex.IsFatal()) { + throw; + } + + Logger.Error(ex, "An unexcepted error occured while terminating the Shell"); } } } diff --git a/src/Orchard/Environment/Extensions/Compilers/DefaultExtensionCompiler.cs b/src/Orchard/Environment/Extensions/Compilers/DefaultExtensionCompiler.cs index 3dfc2d6af..488dcb90a 100644 --- a/src/Orchard/Environment/Extensions/Compilers/DefaultExtensionCompiler.cs +++ b/src/Orchard/Environment/Extensions/Compilers/DefaultExtensionCompiler.cs @@ -8,6 +8,7 @@ using Orchard.FileSystems.Dependencies; using Orchard.FileSystems.VirtualPath; using Orchard.Localization; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Environment.Extensions.Compilers { /// @@ -106,10 +107,13 @@ namespace Orchard.Environment.Extensions.Compilers { } } } - catch (Exception e) { + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } //Note: we need to embed the "e.Message" in the exception text because // ASP.NET build manager "swallows" inner exceptions from this method. - throw new OrchardCoreException(T("Error compiling module \"{0}\" from file \"{1}\":\r\n{2}", moduleName, context.VirtualPath, e.Message), e); + throw new OrchardCoreException(T("Error compiling module \"{0}\" from file \"{1}\":\r\n{2}", moduleName, context.VirtualPath, ex.Message), ex); } } diff --git a/src/Orchard/Environment/Extensions/ExtensionManager.cs b/src/Orchard/Environment/Extensions/ExtensionManager.cs index 3701c9764..4dc8c02d3 100644 --- a/src/Orchard/Environment/Extensions/ExtensionManager.cs +++ b/src/Orchard/Environment/Extensions/ExtensionManager.cs @@ -9,6 +9,7 @@ using Orchard.Localization; using Orchard.Logging; using Orchard.Utility; using Orchard.Utility.Extensions; +using Orchard.Exceptions; namespace Orchard.Environment.Extensions { public class ExtensionManager : IExtensionManager { @@ -119,6 +120,9 @@ namespace Orchard.Environment.Extensions { }); } catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } Logger.Error(ex, "Error loading extension '{0}'", extensionId); throw new OrchardException(T("Error while loading extension '{0}'.", extensionId), ex); } diff --git a/src/Orchard/Environment/Extensions/Folders/ExtensionHarvester.cs b/src/Orchard/Environment/Extensions/Folders/ExtensionHarvester.cs index a6ad55c72..38215b366 100644 --- a/src/Orchard/Environment/Extensions/Folders/ExtensionHarvester.cs +++ b/src/Orchard/Environment/Extensions/Folders/ExtensionHarvester.cs @@ -8,6 +8,7 @@ using Orchard.FileSystems.WebSite; using Orchard.Localization; using Orchard.Logging; using Orchard.Utility.Extensions; +using Orchard.Exceptions; namespace Orchard.Environment.Extensions.Folders { public class ExtensionHarvester : IExtensionHarvester { @@ -98,6 +99,9 @@ namespace Orchard.Environment.Extensions.Folders { } catch (Exception ex) { // Ignore invalid module manifests + if (ex.IsFatal()) { + throw; + } Logger.Error(ex, "The module '{0}' could not be loaded. It was ignored.", extensionId); _criticalErrorProvider.RegisterErrorMessage(T("The extension '{0}' manifest could not be loaded. It was ignored.", extensionId)); } diff --git a/src/Orchard/Environment/IAssemblyLoader.cs b/src/Orchard/Environment/IAssemblyLoader.cs index 410822a45..32722b5f1 100644 --- a/src/Orchard/Environment/IAssemblyLoader.cs +++ b/src/Orchard/Environment/IAssemblyLoader.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using Orchard.Logging; +using Orchard.Exceptions; + namespace Orchard.Environment { public interface IAssemblyLoader { @@ -25,8 +27,11 @@ namespace Orchard.Environment { try { return _loadedAssemblies.GetOrAdd(this.ExtractAssemblyShortName(assemblyName), shortName => LoadWorker(shortName, assemblyName)); } - catch (Exception e) { - Logger.Error(e, "Error loading assembly '{0}'", assemblyName); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error(ex, "Error loading assembly '{0}'", assemblyName); return null; } } diff --git a/src/Orchard/Environment/IBuildManager.cs b/src/Orchard/Environment/IBuildManager.cs index d9ac231ab..40b8c9aa8 100644 --- a/src/Orchard/Environment/IBuildManager.cs +++ b/src/Orchard/Environment/IBuildManager.cs @@ -53,8 +53,9 @@ namespace Orchard.Environment { return BuildManager.GetCompiledAssembly(virtualPath); } catch (Exception ex) { - if (ex.IsFatal()) throw; - + if (ex.IsFatal()) { + throw; + } Logger.Warning(ex, "Error when compiling assembly under {0}.", virtualPath); return null; } diff --git a/src/Orchard/Environment/IHostLocalRestart.cs b/src/Orchard/Environment/IHostLocalRestart.cs index 90a2371d2..f801e6efe 100644 --- a/src/Orchard/Environment/IHostLocalRestart.cs +++ b/src/Orchard/Environment/IHostLocalRestart.cs @@ -5,6 +5,7 @@ using Orchard.Environment.Descriptor; using Orchard.Environment.Descriptor.Models; using Orchard.FileSystems.AppData; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Environment { public interface IHostLocalRestart { @@ -45,8 +46,11 @@ namespace Orchard.Environment { try { _appDataFolder.CreateFile(fileName, "Host Restart"); } - catch(Exception e) { - Logger.Warning(e, "Error updating file '{0}'", fileName); + catch(Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Warning(ex, "Error updating file '{0}'", fileName); } } } diff --git a/src/Orchard/Environment/ViewsBackgroundCompilation.cs b/src/Orchard/Environment/ViewsBackgroundCompilation.cs index 67ae7ac1f..4d5e949d7 100644 --- a/src/Orchard/Environment/ViewsBackgroundCompilation.cs +++ b/src/Orchard/Environment/ViewsBackgroundCompilation.cs @@ -6,6 +6,7 @@ using System.Timers; using System.Web.Compilation; using Orchard.FileSystems.VirtualPath; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Environment { public interface IViewsBackgroundCompilation { @@ -136,10 +137,13 @@ namespace Orchard.Environment { if (firstFile != null) BuildManager.GetCompiledAssembly(firstFile); } - catch(Exception e) { + catch(Exception ex) { + if (ex.IsFatal()) { + throw; + } // Some views might not compile, this is ok and harmless in this // context of pre-compiling views. - Logger.Information(e, "Compilation of directory '{0}' skipped", viewDirectory); + Logger.Information(ex, "Compilation of directory '{0}' skipped", viewDirectory); } stopwatch.Stop(); Logger.Information("Directory '{0}' compiled in {1} msec", viewDirectory, stopwatch.ElapsedMilliseconds); diff --git a/src/Orchard/Events/DefaultOrchardEventBus.cs b/src/Orchard/Events/DefaultOrchardEventBus.cs index d69d84023..adcab90d4 100644 --- a/src/Orchard/Events/DefaultOrchardEventBus.cs +++ b/src/Orchard/Events/DefaultOrchardEventBus.cs @@ -7,6 +7,7 @@ using System.Reflection; using Autofac.Features.Indexed; using Orchard.Exceptions; using Orchard.Localization; +using Orchard.Exceptions; namespace Orchard.Events { public class DefaultOrchardEventBus : IEventBus { @@ -53,6 +54,9 @@ namespace Orchard.Events { return TryInvoke(eventHandler, messageName, interfaceName, methodName, eventData, out returnValue); } catch (Exception exception) { + if (exception.IsFatal()) { + throw; + } if (!_exceptionPolicy.HandleException(this, exception)) { throw; } diff --git a/src/Orchard/FileSystems/AppData/AppDataFolder.cs b/src/Orchard/FileSystems/AppData/AppDataFolder.cs index 02e60e283..092ca9b45 100644 --- a/src/Orchard/FileSystems/AppData/AppDataFolder.cs +++ b/src/Orchard/FileSystems/AppData/AppDataFolder.cs @@ -7,6 +7,7 @@ using Orchard.FileSystems.VirtualPath; using Orchard.Localization; using Orchard.Logging; using Orchard.Validation; +using Orchard.Exceptions; namespace Orchard.FileSystems.AppData { public class AppDataFolder : IAppDataFolder { @@ -78,8 +79,11 @@ namespace Orchard.FileSystems.AppData { try { File.Delete(destinationFileName); } - catch (Exception e) { - throw new OrchardCoreException(T("Unable to make room for file \"{0}\" in \"App_Data\" folder", destinationFileName), e); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + throw new OrchardCoreException(T("Unable to make room for file \"{0}\" in \"App_Data\" folder", destinationFileName), ex); } } diff --git a/src/Orchard/FileSystems/Dependencies/DefaultExtensionDependenciesManager.cs b/src/Orchard/FileSystems/Dependencies/DefaultExtensionDependenciesManager.cs index c917c679d..1afd04077 100644 --- a/src/Orchard/FileSystems/Dependencies/DefaultExtensionDependenciesManager.cs +++ b/src/Orchard/FileSystems/Dependencies/DefaultExtensionDependenciesManager.cs @@ -5,6 +5,7 @@ using System.Xml.Linq; using Orchard.Caching; using Orchard.FileSystems.AppData; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.FileSystems.Dependencies { /// @@ -135,8 +136,11 @@ namespace Orchard.FileSystems.Dependencies { return XDocument.Load(stream); } } - catch (Exception e) { - Logger.Information(e, "Error reading file '{0}'. Assuming empty.", persistancePath); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Information(ex, "Error reading file '{0}'. Assuming empty.", persistancePath); return new XDocument(); } } diff --git a/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs b/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs index 5b6200657..ebcde7b54 100644 --- a/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs +++ b/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs @@ -6,6 +6,7 @@ using System.Web.Hosting; using Orchard.Environment.Configuration; using Orchard.Localization; using Orchard.Validation; +using Orchard.Exceptions; namespace Orchard.FileSystems.Media { public class FileSystemStorageProvider : IStorageProvider { @@ -155,6 +156,9 @@ namespace Orchard.FileSystems.Media { directoryInfo.Create(); } catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } throw new ArgumentException(T("The folder could not be created at path: {0}. {1}", path, ex).ToString()); } } diff --git a/src/Orchard/FileSystems/VirtualPath/DefaultVirtualPathProvider.cs b/src/Orchard/FileSystems/VirtualPath/DefaultVirtualPathProvider.cs index 85a295d1b..4c2941e91 100644 --- a/src/Orchard/FileSystems/VirtualPath/DefaultVirtualPathProvider.cs +++ b/src/Orchard/FileSystems/VirtualPath/DefaultVirtualPathProvider.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Web; using System.Web.Hosting; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.FileSystems.VirtualPath { public class DefaultVirtualPathProvider : IVirtualPathProvider { @@ -59,9 +60,12 @@ namespace Orchard.FileSystems.VirtualPath { } return result; } - catch (Exception e) { + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } // The initial path might have been invalid (e.g. path indicates a path outside the application root) - Logger.Information(e, "Path '{0}' cannot be made app relative", virtualPath); + Logger.Information(ex, "Path '{0}' cannot be made app relative", virtualPath); return null; } } @@ -156,8 +160,11 @@ namespace Orchard.FileSystems.VirtualPath { try { return FileExists(virtualPath); } - catch (Exception e) { - Logger.Information(e, "File '{0}' can not be checked for existence. Assuming doesn't exist.", virtualPath); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Information(ex, "File '{0}' can not be checked for existence. Assuming doesn't exist.", virtualPath); return false; } } diff --git a/src/Orchard/Messaging/Services/DefaultMessageManager.cs b/src/Orchard/Messaging/Services/DefaultMessageManager.cs index 8e2911857..1495f9e37 100644 --- a/src/Orchard/Messaging/Services/DefaultMessageManager.cs +++ b/src/Orchard/Messaging/Services/DefaultMessageManager.cs @@ -5,6 +5,7 @@ using Orchard.Logging; using Orchard.Messaging.Events; using Orchard.Messaging.Models; using Orchard.ContentManagement.Records; +using Orchard.Exceptions; namespace Orchard.Messaging.Services { [Obsolete] @@ -40,8 +41,11 @@ namespace Orchard.Messaging.Services { PrepareAndSend(type, properties, context); } - catch ( Exception e ) { - Logger.Error(e, "An error occured while sending the message {0}", type); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error(ex, "An error occured while sending the message {0}", type); } } @@ -60,8 +64,11 @@ namespace Orchard.Messaging.Services { PrepareAndSend(type, properties, context); } - catch (Exception e) { - Logger.Error(e, "An error occured while sending the message {0}", type); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error(ex, "An error occured while sending the message {0}", type); } } diff --git a/src/Orchard/Mvc/MvcModule.cs b/src/Orchard/Mvc/MvcModule.cs index 4125c4706..33cc7176d 100644 --- a/src/Orchard/Mvc/MvcModule.cs +++ b/src/Orchard/Mvc/MvcModule.cs @@ -11,6 +11,7 @@ using System.Web.Routing; using Autofac; using Orchard.Mvc.Routes; using Orchard.Settings; +using Orchard.Exceptions; namespace Orchard.Mvc { public class MvcModule : Module { @@ -31,7 +32,11 @@ namespace Orchard.Mvc { // The "Request" property throws at application startup on IIS integrated pipeline mode. var req = HttpContext.Current.Request; } - catch (Exception) { + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + return false; } diff --git a/src/Orchard/Tasks/BackgroundService.cs b/src/Orchard/Tasks/BackgroundService.cs index d796a2d0d..36d55b252 100644 --- a/src/Orchard/Tasks/BackgroundService.cs +++ b/src/Orchard/Tasks/BackgroundService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Orchard.Data; using Orchard.Environment.Configuration; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Tasks { @@ -39,9 +40,13 @@ namespace Orchard.Tasks { task.Sweep(); Logger.Information("Finished processing background task \"{0}\" on tenant \"{1}\".", taskName, _shellName); } - catch (Exception e) { + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + _transactionManager.Cancel(); - Logger.Error(e, "Error while processing background task \"{0}\" on tenant \"{1}\".", taskName, _shellName); + Logger.Error(ex, "Error while processing background task \"{0}\" on tenant \"{1}\".", taskName, _shellName); } } } diff --git a/src/Orchard/Tasks/SweepGenerator.cs b/src/Orchard/Tasks/SweepGenerator.cs index feb8a3f0e..44429e50b 100644 --- a/src/Orchard/Tasks/SweepGenerator.cs +++ b/src/Orchard/Tasks/SweepGenerator.cs @@ -1,6 +1,7 @@ using System; using System.Timers; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Tasks { @@ -51,6 +52,10 @@ namespace Orchard.Tasks { } } catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Warning(ex, "Problem in background tasks"); } finally { diff --git a/src/Orchard/Time/SiteTimeZoneSelector.cs b/src/Orchard/Time/SiteTimeZoneSelector.cs index 28068b213..366718216 100644 --- a/src/Orchard/Time/SiteTimeZoneSelector.cs +++ b/src/Orchard/Time/SiteTimeZoneSelector.cs @@ -1,6 +1,7 @@ using System; using System.Web; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Time { /// @@ -31,8 +32,11 @@ namespace Orchard.Time { TimeZone = TimeZoneInfo.FindSystemTimeZoneById(siteTimeZoneId) }; } - catch(Exception e) { - Logger.Error(e, "TimeZone could not be loaded"); + catch(Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error(ex, "TimeZone could not be loaded"); // if the database could not be updated in time, ignore this provider return null; diff --git a/src/Orchard/UI/Admin/Notification/NotificationManager.cs b/src/Orchard/UI/Admin/Notification/NotificationManager.cs index 327b4f1c1..d0529224c 100644 --- a/src/Orchard/UI/Admin/Notification/NotificationManager.cs +++ b/src/Orchard/UI/Admin/Notification/NotificationManager.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Orchard.Logging; using Orchard.UI.Notify; +using Orchard.Exceptions; namespace Orchard.UI.Admin.Notification { public class NotificationManager : INotificationManager { @@ -22,8 +23,11 @@ namespace Orchard.UI.Admin.Notification { try { return n.GetNotifications(); } - catch(Exception e) { - Logger.Error("An unhandled exception was thrown while generating a notification: " + n.GetType(), e); + catch(Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error("An unhandled exception was thrown while generating a notification: " + n.GetType(), ex); return Enumerable.Empty(); } }).ToList(); From 9947f3973e73b54bbd77d6e10c8afd31590aa1a6 Mon Sep 17 00:00:00 2001 From: Thierry Fleury Date: Fri, 24 Jul 2015 17:32:59 +0200 Subject: [PATCH 12/25] Add new Chain method for tokens The new method allows working with parameterized tokens. --- .../Modules/Orchard.Tokens/EvaluateFor.cs | 1 + .../Implementation/TokenManager.cs | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/EvaluateFor.cs b/src/Orchard.Web/Modules/Orchard.Tokens/EvaluateFor.cs index 39bda24bc..70438592c 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/EvaluateFor.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/EvaluateFor.cs @@ -7,5 +7,6 @@ namespace Orchard.Tokens { public abstract EvaluateFor Chain(string token, string chainTarget, Func chainValue); public abstract EvaluateFor Token(Func tokenValue); public abstract EvaluateFor Token(Func filter, Func tokenValue); + public abstract EvaluateFor Chain(Func> filter, string chainTarget, Func chainValue); } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Implementation/TokenManager.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Implementation/TokenManager.cs index b87d6f353..c0a967914 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Implementation/TokenManager.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Implementation/TokenManager.cs @@ -153,6 +153,27 @@ namespace Orchard.Tokens.Implementation { } return this; } + + public override EvaluateFor Chain(Func> filter, string chainTarget, Func chainValue) { + var subTokens = _context.Tokens + .Where(kv => kv.Key.Contains('.')) + .Select(kv => { + var filterResult = filter(kv.Key); + return filterResult != null ? new Tuple(filterResult.Item1, filterResult.Item2, kv.Value) : null; + }) + .Where(st => st != null) + .ToList(); + if (!subTokens.Any()) { + return this; + } + foreach(var chainGroup in subTokens.GroupBy(st => st.Item1)) { + var subValues = _context._manager.Evaluate(chainTarget, chainGroup.ToDictionary(cg => cg.Item2, cg => cg.Item3), new Dictionary { { chainTarget, chainValue(chainGroup.Key, _data) } }); + foreach (var subValue in subValues) { + _context.Values[subValue.Key] = subValue.Value; + } + } + return this; + } } private class EvaluateForSilent : EvaluateFor { @@ -175,6 +196,10 @@ namespace Orchard.Tokens.Implementation { public override EvaluateFor Chain(string token, string chainTarget, Func chainValue) { return this; } + + public override EvaluateFor Chain(Func> filter, string chainTarget, Func chainValue) { + return this; + } } } From 75f3a618f08d5d01ebafd43d1a4fd39cb7e3ccee Mon Sep 17 00:00:00 2001 From: Thierry Fleury Date: Fri, 24 Jul 2015 17:35:41 +0200 Subject: [PATCH 13/25] Enhances TaxonomyField's token chaining. --- .../Tokens/TaxonomyTokens.cs | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Tokens/TaxonomyTokens.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/Tokens/TaxonomyTokens.cs index 3b2a9edc2..e921232ed 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Tokens/TaxonomyTokens.cs +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Tokens/TaxonomyTokens.cs @@ -31,21 +31,33 @@ namespace Orchard.Taxonomies.Tokens { context.For("TaxonomyField") .Token("Terms", field => String.Join(", ", field.Terms.Select(t => t.Name).ToArray())) - .Token( - token => { - var index = 0; - return (token.StartsWith("Terms:", StringComparison.OrdinalIgnoreCase) && int.TryParse(token.Substring("Terms:".Length), out index)) ? index.ToString() : null; - }, - (token, t) => { - var index = Convert.ToInt32(token); - return index + 1 > t.Terms.Count() ? null : t.Terms.ElementAt(index).Name; + .Token(FilterTokenParam, + (index, field) => { + var term = field.Terms.ElementAtOrDefault(Convert.ToInt32(index)); + return term != null ? term.Name : null; }) - // todo: extend Chain() in order to accept a filter like in Token() so that we can chain on an expression - .Chain("Terms:0", "Content", t => t.Terms.ElementAt(0)) - .Chain("Terms:1", "Content", t => t.Terms.ElementAt(1)) - .Chain("Terms:2", "Content", t => t.Terms.ElementAt(2)) - .Chain("Terms:3", "Content", t => t.Terms.ElementAt(3)) + .Chain(FilterChainParam, "Content", (index, field) => field.Terms.ElementAtOrDefault(Convert.ToInt32(index))) ; } + + private static string FilterTokenParam(string token) { + int index = 0; + return (token.StartsWith("Terms:", StringComparison.OrdinalIgnoreCase) && int.TryParse(token.Substring("Terms:".Length), out index)) ? index.ToString() : null; + } + + private static Tuple FilterChainParam(string token) { + int tokenLength = "Terms:".Length; + int index = 0; + int chainIndex = token.IndexOf('.'); + if (!token.StartsWith("Terms:", StringComparison.OrdinalIgnoreCase) || chainIndex <= tokenLength) + return null; + + if (int.TryParse(token.Substring(tokenLength, chainIndex - tokenLength), out index)) { + return new Tuple(index.ToString(), token.Substring(chainIndex + 1)); + } + else { + return null; + } + } } } \ No newline at end of file From 25c34d8bcae5b83c86793a7c4011a35fd9d8cdba Mon Sep 17 00:00:00 2001 From: Thierry Fleury Date: Fri, 24 Jul 2015 17:39:10 +0200 Subject: [PATCH 14/25] Fixes #5563 : Allow token chaining on DynamicForms submissions. --- .../Orchard.DynamicForms/Tokens/FormTokens.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Tokens/FormTokens.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Tokens/FormTokens.cs index e26cb2626..68fbdb5c4 100644 --- a/src/Orchard.Web/Modules/Orchard.DynamicForms/Tokens/FormTokens.cs +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Tokens/FormTokens.cs @@ -7,7 +7,7 @@ namespace Orchard.DynamicForms.Tokens { public void Describe(DescribeContext context) { context.For("FormSubmission", T("Dynamic Form submission"), T("Dynamic Form Submission tokens for use in workflows handling the Dynamic Form Submitted event.")) - .Token("Field:*", T("Field:"), T("The posted field value to access.")) + .Token("Field:*", T("Field:"), T("The posted field value to access."), "Text") .Token("IsValid:*", T("IsValid:"), T("The posted field validation status.")) ; } @@ -15,10 +15,20 @@ namespace Orchard.DynamicForms.Tokens { public void Evaluate(EvaluateContext context) { context.For("FormSubmission") .Token(token => token.StartsWith("Field:", StringComparison.OrdinalIgnoreCase) ? token.Substring("Field:".Length) : null, GetFieldValue) + .Chain(FilterChainParam, "Text", GetFieldValue) .Token(token => token.StartsWith("IsValid:", StringComparison.OrdinalIgnoreCase) ? token.Substring("IsValid:".Length) : null, GetFieldValidationStatus); } - private object GetFieldValue(string fieldName, FormSubmissionTokenContext context) { + private static Tuple FilterChainParam(string token) { + int tokenLength = "Field:".Length; + int chainIndex = token.IndexOf('.'); + if (token.StartsWith("Field:", StringComparison.OrdinalIgnoreCase) && chainIndex > tokenLength) + return new Tuple(token.Substring(tokenLength, chainIndex - tokenLength), token.Substring(chainIndex + 1)); + else + return null; + } + + private string GetFieldValue(string fieldName, FormSubmissionTokenContext context) { return context.PostedValues[fieldName]; } From 67e7d1074e9a91984577fc2d50d9bb12e0eab9d9 Mon Sep 17 00:00:00 2001 From: Thierry Fleury Date: Fri, 24 Jul 2015 17:42:07 +0200 Subject: [PATCH 15/25] Allow Text token chaining when possible. Correct some errors on token descriptions. --- .../Orchard.Tokens/Providers/ContentTokens.cs | 2 +- .../Orchard.Tokens/Providers/TextTokens.cs | 36 ++++++++++--------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Providers/ContentTokens.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Providers/ContentTokens.cs index 257394d88..6e6dad645 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Providers/ContentTokens.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Providers/ContentTokens.cs @@ -36,7 +36,7 @@ namespace Orchard.Tokens.Providers { .Token("DisplayUrl", T("Display Url"), T("Url to display the content."), "Url") .Token("EditUrl", T("Edit Url"), T("Url to edit the content."), "Url") .Token("Container", T("Container"), T("The container Content Item."), "Content") - .Token("Body", T("Body"), T("The body text of the content item."), "Content") + .Token("Body", T("Body"), T("The body text of the content item."), "Text") ; // Token descriptors for fields diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Providers/TextTokens.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Providers/TextTokens.cs index 89f77c018..045d67e09 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Providers/TextTokens.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Providers/TextTokens.cs @@ -13,38 +13,42 @@ namespace Orchard.Tokens.Providers { public void Describe(DescribeContext context) { context.For("Text", T("Text"), T("Tokens for text strings")) .Token("Limit:*", T("Limit:[,]"), T("Limit text to specified length and append an optional ellipsis text.")) - .Token("Format:*", T("Format:"), T("Optional format specifier (e.g. foo{0}bar). See format strings at Standard Formats and Custom Formats"), "DateTime") - .Token("TrimEnd:*", T("TrimEnd:"), T("Trims the specified characters or number of them from the end of the string."), "Text") + .Token("Format:*", T("Format:"), T("Optional format specifier (e.g. foo{0}bar).")) + .Token("TrimEnd:*", T("TrimEnd:"), T("Trims the specified characters or number of them from the end of the string.")) .Token("UrlEncode", T("Url Encode"), T("Encodes a URL string."), "Text") .Token("HtmlEncode", T("Html Encode"), T("Encodes an HTML string."), "Text") - .Token("LineEncode", T("Line Encode"), T("Replaces new lines with
tags.")) + .Token("LineEncode", T("Line Encode"), T("Replaces new lines with
tags."), "Text") ; } public void Evaluate(EvaluateContext context) { context.For("Text", () => "") - .Token( // {Text} + // {Text} + .Token( token => token == String.Empty ? String.Empty : null, (token, d) => d.ToString()) - .Token( // {Text.Limit:[,]} - token => { - if (token.StartsWith("Limit:", StringComparison.OrdinalIgnoreCase)) { - var param = token.Substring("Limit:".Length); - return param; - } - return null; - }, + // {Text.Limit:[,]} + .Token( + token => FilterTokenParam("Limit:", token), (token, t) => Limit(t, token)) // {Text.Format:} .Token( - token => token.StartsWith("Format:", StringComparison.OrdinalIgnoreCase) ? token.Substring("Format:".Length) : null, - (token, d) => String.Format(d,token)) - .Token(token => token.StartsWith("TrimEnd:", StringComparison.OrdinalIgnoreCase) ? token.Substring("TrimEnd:".Length) : null, TrimEnd) + token => FilterTokenParam("Format:", token), + (token, d) => String.Format(d, token)) + // {Text.TrimEnd:} + .Token(token => FilterTokenParam("TrimEnd:", token), TrimEnd) .Token("UrlEncode", HttpUtility.UrlEncode) + .Chain("UrlEncode", "Text", HttpUtility.UrlEncode) .Token("HtmlEncode", HttpUtility.HtmlEncode) + .Chain("HtmlEncode", "Text", HttpUtility.HtmlEncode) .Token("LineEncode", text => text.Replace(System.Environment.NewLine, "
")) + .Chain("LineEncode", "Text", text => text.Replace(System.Environment.NewLine, "
")) ; - + + } + + private static string FilterTokenParam(string tokenName, string token) { + return token.StartsWith(tokenName, StringComparison.OrdinalIgnoreCase) ? token.Substring(tokenName.Length) : null; } private static string TrimEnd(string token, string param) { From 371238a882ed1423f66621ff2e6ea59f6149935d Mon Sep 17 00:00:00 2001 From: Thierry Fleury Date: Mon, 7 Sep 2015 15:14:20 +0200 Subject: [PATCH 16/25] Add parameterized tokens tests --- .../Orchard.Tokens/Tests/TestTokenProvider.cs | 28 +++++++++++++++++++ .../Orchard.Tokens/Tests/TokenizerTests.cs | 12 ++++++++ 2 files changed, 40 insertions(+) diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TestTokenProvider.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TestTokenProvider.cs index 105f705d4..c65b76a65 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TestTokenProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TestTokenProvider.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using Orchard.ContentManagement; using Orchard.Localization; using Orchard.Security; @@ -24,6 +25,9 @@ namespace Orchard.Tokens.Tests { context.For("Date") .Token("Now", T("Now"), T("Current system date in short date format. You can chain a .NET DateTime format string to customize.")); + + context.For("Users") + .Token("Users[*:]", T("Users"), T("A user by its username"), "User"); } public void Evaluate(EvaluateContext context) { @@ -36,6 +40,7 @@ namespace Orchard.Tokens.Tests { context.For("User", () => new TestUser { UserName = "CurrentUser" }) .Token("Name", u => u.UserName) + .Token("Email", u => u.Email) .Token("Birthdate", u => "Nov 15") .Chain("Birthdate", "DateTime", u => new DateTime(1978, 11, 15)); @@ -45,6 +50,29 @@ namespace Orchard.Tokens.Tests { context.For("DateTime") .Token((token, value) => value.ToString(token)); + + context.For("Users", () => new TestUser[] { + new TestUser { UserName = "User1", Email = "user1@test.com" }, + new TestUser { UserName = "User2", Email = "user2@test.com" }, + new TestUser { UserName = "User3", Email = "user3@test.com" } + }) + .Token( + (token) => token.StartsWith("User:", StringComparison.OrdinalIgnoreCase) ? token.Substring("User:".Length) : null, + (userName, users) => users.Where(u => u.UserName == userName).Select(u => u.UserName).FirstOrDefault() + ) + .Chain( + (token) => { + int tokenLength = "User:".Length; + int chainIndex = token.IndexOf('.'); + if (token.StartsWith("User:", StringComparison.OrdinalIgnoreCase) && chainIndex > tokenLength) + return new Tuple(token.Substring(tokenLength, chainIndex - tokenLength), token.Substring(chainIndex + 1)); + else + return null; + }, + "User", + (userName, users) => users.Where(u => u.UserName == userName).FirstOrDefault() + ); + } } diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenizerTests.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenizerTests.cs index 999c3d87b..8c976f8d0 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenizerTests.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenizerTests.cs @@ -40,6 +40,18 @@ namespace Orchard.Tokens.Tests { Assert.That(_tokenizer.Replace("{Site.CurrentUser.Birthdate.yyyy}", null), Is.EqualTo("1978")); } + [Test] + public void TestParameterizedTokens() { + Assert.That(_tokenizer.Replace("{Users.User:User2}", null), Is.EqualTo("User2")); + Assert.That(_tokenizer.Replace("{Users.User:FakeUser}", null), Is.EqualTo("")); + } + + [Test] + public void TestParameterizedChainedTokens() { + Assert.That(_tokenizer.Replace("{Users.User:User2.Email}", null), Is.EqualTo("user2@test.com")); + Assert.That(_tokenizer.Replace("{Users.User:FakeUser.Email}", null), Is.EqualTo("")); + } + [Test] public void TestMissingTokens() { Assert.That(_tokenizer.Replace("[{Site.NotAToken}]", null), Is.EqualTo("[]")); From 2a0f866f26eb0f9a86abd5648f5aece66054e4f4 Mon Sep 17 00:00:00 2001 From: Lombiq Date: Tue, 8 Sep 2015 01:01:23 +0200 Subject: [PATCH 17/25] Fixing exception when importing Projection Elements with the default layout selected Fixed the export of this previously, this was remaining. --- .../Modules/Orchard.Layouts/Drivers/ProjectionElementDriver.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Drivers/ProjectionElementDriver.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Drivers/ProjectionElementDriver.cs index d5d455290..68c7efe4d 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Drivers/ProjectionElementDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Drivers/ProjectionElementDriver.cs @@ -307,10 +307,9 @@ namespace Orchard.Layouts.Drivers { var queryPart = query.As(); var layoutIndex = XmlHelper.Parse(context.ExportableData.Get("LayoutIndex")); - var layout = queryPart.Layouts[layoutIndex]; element.QueryId = queryPart.Id; - element.LayoutId = layout.Id; + element.LayoutId = layoutIndex != -1 ? queryPart.Layouts[layoutIndex].Id : -1; } private static string GetLayoutDescription(IEnumerable layouts, LayoutRecord l) { From 9bac35b3f1735da01609ac769ce48f50bff624cd Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Tue, 8 Sep 2015 09:12:26 -0700 Subject: [PATCH 18/25] Removing duplicated using --- src/Orchard/Events/DefaultOrchardEventBus.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Orchard/Events/DefaultOrchardEventBus.cs b/src/Orchard/Events/DefaultOrchardEventBus.cs index adcab90d4..2a5faf49e 100644 --- a/src/Orchard/Events/DefaultOrchardEventBus.cs +++ b/src/Orchard/Events/DefaultOrchardEventBus.cs @@ -7,7 +7,6 @@ using System.Reflection; using Autofac.Features.Indexed; using Orchard.Exceptions; using Orchard.Localization; -using Orchard.Exceptions; namespace Orchard.Events { public class DefaultOrchardEventBus : IEventBus { From c4592aa65fd386d90f60e2dc6dc1fb84d5e491f0 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Tue, 8 Sep 2015 09:27:36 -0700 Subject: [PATCH 19/25] Selecting the layer "Default" on the widgets start screen Fixes a specflow bug which expect "Default" to be the default selected layer. Appeared since layers are ordered alphabetically. --- .../Modules/Orchard.Widgets/Controllers/AdminController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs index 7daa44705..9c7fa0a0b 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs @@ -69,7 +69,7 @@ namespace Orchard.Widgets.Controllers { } LayerPart currentLayer = layerId == null - ? layers.FirstOrDefault() + ? layers.FirstOrDefault(x => x.Name == "Default") : layers.FirstOrDefault(layer => layer.Id == layerId); if (currentLayer == null && layerId != null) { // Incorrect layer id passed From 2bb7eb2f91f6cc44972d841818d61ba6f385c5cf Mon Sep 17 00:00:00 2001 From: Jamie Phillips Date: Tue, 8 Sep 2015 13:06:04 -0400 Subject: [PATCH 20/25] Updating DynamicForms Module.txt The CustomForms module name and website were listed. --- src/Orchard.Web/Modules/Orchard.DynamicForms/Module.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Module.txt b/src/Orchard.Web/Modules/Orchard.DynamicForms/Module.txt index 7000b659c..8b8cb0e99 100644 --- a/src/Orchard.Web/Modules/Orchard.DynamicForms/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Module.txt @@ -1,7 +1,7 @@ -Name: Custom Forms +Name: Dynamic Forms AntiForgery: enabled Author: The Orchard Team -Website: http://orchardcustomforms.codeplex.com +Website: http://www.orchardproject.net/ Version: 1.9.1 OrchardVersion: 1.9 Description: Create custom forms like contact forms using layouts. From 691809cd8583fc6c3414b5ae948f66c83605a096 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Tue, 8 Sep 2015 15:39:19 -0700 Subject: [PATCH 21/25] [Fixes #5733] Update default Layout state settings --- .../Orchard.DynamicForms/Migrations.cs | 52 ++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Migrations.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Migrations.cs index 3aa00e1f9..04fbe114f 100644 --- a/src/Orchard.Web/Modules/Orchard.DynamicForms/Migrations.cs +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Migrations.cs @@ -1,10 +1,15 @@ using System; +using System.Linq; +using System.Security.Cryptography; using Orchard.ContentManagement.MetaData; using Orchard.Core.Contents.Extensions; +using Orchard.Data; using Orchard.Data.Migration; namespace Orchard.DynamicForms { public class Migrations : DataMigrationImpl { + private readonly byte[] _oldLayoutHash = new byte[] { 0x91, 0x10, 0x3b, 0x97, 0xce, 0x1e, 0x1e, 0xc7, 0x7a, 0x41, 0xf7, 0x82, 0xe8, 0x58, 0x85, 0x91 }; + private const string DefaultFormLayoutData = @"{ ""elements"": [ @@ -59,7 +64,52 @@ namespace Orchard.DynamicForms { .WithSetting("LayoutTypePartSettings.DefaultLayoutData", DefaultFormLayoutData)) .WithSetting("Stereotype", "Widget") .DisplayedAs("Form Widget")); - return 1; + return 2; + } + + public int UpdateFrom1() { + // if the default layout data was unchanged, fix it with the new default + + var formLayoutPart = ContentDefinitionManager + .GetTypeDefinition("Form") + .Parts + .FirstOrDefault(x => x.PartDefinition.Name == "LayoutPart"); + + if (formLayoutPart != null && + formLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"] != null) { + var layout = formLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"]; + + if(GetMD5(layout) == _oldLayoutHash) { + ContentDefinitionManager.AlterTypeDefinition("Form", type => type + .WithPart("LayoutPart", p => p + .WithSetting("LayoutTypePartSettings.DefaultLayoutData", DefaultFormLayoutData)) + ); + } + } + + var formWidgetLayoutPart = ContentDefinitionManager + .GetTypeDefinition("FormWidget") + .Parts + .FirstOrDefault(x => x.PartDefinition.Name == "LayoutPart"); + + if (formWidgetLayoutPart != null && + formWidgetLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"] != null) { + var layout = formWidgetLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"]; + + if (GetMD5(layout) == _oldLayoutHash) { + ContentDefinitionManager.AlterTypeDefinition("FormWidget", type => type + .WithPart("LayoutPart", p => p + .WithSetting("LayoutTypePartSettings.DefaultLayoutData", DefaultFormLayoutData)) + ); + } + } + + return 2; + } + + private byte[] GetMD5(string text) { + byte[] encodedText = System.Text.Encoding.UTF8.GetBytes(text); + return ((HashAlgorithm)CryptoConfig.CreateFromName("MD5")).ComputeHash(encodedText); } } } \ No newline at end of file From 2f2134412e85ca4aab6da507f71558e0d1c29d36 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Tue, 8 Sep 2015 16:13:55 -0700 Subject: [PATCH 22/25] [Fixes #5492] Adding JavaScriptEncode token --- src/Orchard.Web/Modules/Orchard.Tokens/Providers/TextTokens.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Providers/TextTokens.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Providers/TextTokens.cs index 045d67e09..255cee809 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Providers/TextTokens.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Providers/TextTokens.cs @@ -17,6 +17,7 @@ namespace Orchard.Tokens.Providers { .Token("TrimEnd:*", T("TrimEnd:"), T("Trims the specified characters or number of them from the end of the string.")) .Token("UrlEncode", T("Url Encode"), T("Encodes a URL string."), "Text") .Token("HtmlEncode", T("Html Encode"), T("Encodes an HTML string."), "Text") + .Token("JavaScriptEncode", T("JavaScript Encode"), T("Encodes a JavaScript string."), "Text") .Token("LineEncode", T("Line Encode"), T("Replaces new lines with
tags."), "Text") ; } @@ -41,6 +42,8 @@ namespace Orchard.Tokens.Providers { .Chain("UrlEncode", "Text", HttpUtility.UrlEncode) .Token("HtmlEncode", HttpUtility.HtmlEncode) .Chain("HtmlEncode", "Text", HttpUtility.HtmlEncode) + .Token("JavaScriptEncode", HttpUtility.JavaScriptStringEncode) + .Chain("JavaScriptEncode", "Text", HttpUtility.JavaScriptStringEncode) .Token("LineEncode", text => text.Replace(System.Environment.NewLine, "
")) .Chain("LineEncode", "Text", text => text.Replace(System.Environment.NewLine, "
")) ; From c83f5d88cbdd1e1b4f603d2e5554f012a9f5e16b Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Tue, 8 Sep 2015 17:04:45 -0700 Subject: [PATCH 23/25] Supporting lazy cache manager resolution --- src/Orchard.Tests/Caching/CacheTests.cs | 38 +++++++++++++++++++ .../Metadata/ContentDefinitionManager.cs | 6 +-- .../Core/Settings/Services/SiteService.cs | 2 +- .../Services/StereotypeService.cs | 2 +- .../Services/ElementManager.cs | 4 +- .../ImageProcessingFileNameProvider.cs | 2 +- .../Services/ImageProfileService.cs | 2 +- .../Filters/OutputCacheFilter.cs | 2 +- .../Services/CacheService.cs | 2 +- .../Services/RubyScriptExpressionEvaluator.cs | 4 +- .../ScriptExpressionEvaluator.cs | 2 +- .../Orchard.Tags/Services/TagCloudService.cs | 2 +- .../Services/TemplateShapeBindingResolver.cs | 2 +- src/Orchard/Caching/ICacheManager.cs | 13 +++++++ .../DefaultContentManager.cs | 2 +- .../ContentManagement/DefaultContentQuery.cs | 2 +- .../Descriptors/DefaultShapeTableManager.cs | 2 +- .../PlacementFileParser.cs | 2 +- .../ShapeTemplateBindingStrategy.cs | 2 +- .../Compilers/DefaultProjectFileParser.cs | 2 +- .../Extensions/ExtensionManager.cs | 8 ++-- .../Extensions/Folders/ExtensionHarvester.cs | 4 +- .../Environment/IAssemblyNameResolver.cs | 2 +- .../Dependencies/DefaultDependenciesFolder.cs | 2 +- .../DefaultExtensionDependenciesManager.cs | 2 +- .../Services/DefaultCultureManager.cs | 2 +- .../Services/DefaultLocalizedStringManager.cs | 2 +- 27 files changed, 84 insertions(+), 33 deletions(-) diff --git a/src/Orchard.Tests/Caching/CacheTests.cs b/src/Orchard.Tests/Caching/CacheTests.cs index 13af703fb..0201d3b26 100644 --- a/src/Orchard.Tests/Caching/CacheTests.cs +++ b/src/Orchard.Tests/Caching/CacheTests.cs @@ -1,4 +1,6 @@ using System; +using System.Linq; +using System.Threading; using Autofac; using NUnit.Framework; using Orchard.Caching; @@ -78,6 +80,42 @@ namespace Orchard.Tests.Caching { Is.Not.SameAs(c2.CacheManager.GetCache())); } + [Test] + public void CacheManagerIsNotBlocking() { + var hits = 0; + string result = ""; + + Enumerable.Range(0, 5).AsParallel().ForAll(x => + result = _cacheManager.Get("testItem", ctx => { + // by waiting for 100ms we expect all the calls to Get + // to enter this lambda + Thread.Sleep(100); + hits++; + return "testResult"; + }) + ); + + Assert.That(result, Is.EqualTo("testResult")); + Assert.That(hits, Is.GreaterThan(1)); + } + + [Test] + public void CacheManagerIsBlocking() { + var hits = 0; + string result = ""; + + Enumerable.Range(0, 5).AsParallel().ForAll(x => + result = _cacheManager.Get("testItem", true, ctx => { + Thread.Sleep(100); + hits++; + return "testResult"; + }) + ); + + Assert.That(result, Is.EqualTo("testResult")); + Assert.That(hits, Is.EqualTo(1)); + } + class ComponentOne { public ICacheManager CacheManager { get; set; } diff --git a/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs b/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs index 16c1d1f78..3ebb1b4ed 100644 --- a/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs +++ b/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs @@ -125,7 +125,7 @@ namespace Orchard.Core.Settings.Metadata { } private IDictionary AcquireContentTypeDefinitions() { - return _cacheManager.Get("ContentTypeDefinitions", ctx => { + return _cacheManager.Get("ContentTypeDefinitions", true, ctx => { MonitorContentDefinitionSignal(ctx); AcquireContentPartDefinitions(); @@ -140,7 +140,7 @@ namespace Orchard.Core.Settings.Metadata { } private IDictionary AcquireContentPartDefinitions() { - return _cacheManager.Get("ContentPartDefinitions", ctx => { + return _cacheManager.Get("ContentPartDefinitions", true, ctx => { MonitorContentDefinitionSignal(ctx); var contentPartDefinitionRecords = _partDefinitionRepository.Table @@ -153,7 +153,7 @@ namespace Orchard.Core.Settings.Metadata { } private IDictionary AcquireContentFieldDefinitions() { - return _cacheManager.Get("ContentFieldDefinitions", ctx => { + return _cacheManager.Get("ContentFieldDefinitions", true, ctx => { MonitorContentDefinitionSignal(ctx); return _fieldDefinitionRepository.Table.Select(Build).ToDictionary(x => x.Name, y => y); diff --git a/src/Orchard.Web/Core/Settings/Services/SiteService.cs b/src/Orchard.Web/Core/Settings/Services/SiteService.cs index b83f23caa..721a3f619 100644 --- a/src/Orchard.Web/Core/Settings/Services/SiteService.cs +++ b/src/Orchard.Web/Core/Settings/Services/SiteService.cs @@ -24,7 +24,7 @@ namespace Orchard.Core.Settings.Services { public ILogger Logger { get; set; } public ISite GetSiteSettings() { - var siteId = _cacheManager.Get("SiteId", ctx => { + var siteId = _cacheManager.Get("SiteId", true, ctx => { var site = _contentManager.Query("Site") .List() .FirstOrDefault(); diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/StereotypeService.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/StereotypeService.cs index c00221328..4b4e8471a 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/StereotypeService.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/StereotypeService.cs @@ -22,7 +22,7 @@ namespace Orchard.ContentTypes.Services { } public IEnumerable GetStereotypes() { - return _cacheManager.Get("ContentType.Stereotypes", context => { + return _cacheManager.Get("ContentType.Stereotypes", true, context => { // TODO: Implement a signal in ContentDefinitionManager that gets raised whenever a type definition is updated. // For now, we'll just cache the stereotypes for 1 minute. diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementManager.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementManager.cs index fd5b94c8a..9bcb5075b 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementManager.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementManager.cs @@ -38,7 +38,7 @@ namespace Orchard.Layouts.Services { public IEnumerable DescribeElements(DescribeElementsContext context) { var contentType = context.Content != null ? context.Content.ContentItem.ContentType : default(string); var cacheKey = String.Format("LayoutElementTypes-{0}-{1}", contentType ?? "AnyType", context.CacheVaryParam); - return _cacheManager.Get(cacheKey, acquireContext => { + return _cacheManager.Get(cacheKey, true, acquireContext => { var harvesterContext = new HarvestElementsContext { Content = context.Content }; @@ -55,7 +55,7 @@ namespace Orchard.Layouts.Services { public IEnumerable GetCategories(DescribeElementsContext context) { var contentType = context.Content != null ? context.Content.ContentItem.ContentType : default(string); - return _cacheManager.Get(String.Format("ElementCategories-{0}-{1}", contentType ?? "AnyType", context.CacheVaryParam), acquireContext => { + return _cacheManager.Get(String.Format("ElementCategories-{0}-{1}", contentType ?? "AnyType", context.CacheVaryParam), true, acquireContext => { var elements = DescribeElements(context); var categoryDictionary = GetCategories(); var categoryDescriptorDictionary = new Dictionary(); diff --git a/src/Orchard.Web/Modules/Orchard.MediaProcessing/Services/ImageProcessingFileNameProvider.cs b/src/Orchard.Web/Modules/Orchard.MediaProcessing/Services/ImageProcessingFileNameProvider.cs index f8a7cf19a..340c2031d 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaProcessing/Services/ImageProcessingFileNameProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaProcessing/Services/ImageProcessingFileNameProvider.cs @@ -58,7 +58,7 @@ namespace Orchard.MediaProcessing.Services { } private IDictionary GetProfileCache(string profile) { - return _cacheManager.Get("MediaProcessing_" + profile, ctx => { + return _cacheManager.Get("MediaProcessing_" + profile, true, ctx => { ctx.Monitor(_signals.When("MediaProcessing_Saved_" + profile)); var dictionary = new Dictionary(); diff --git a/src/Orchard.Web/Modules/Orchard.MediaProcessing/Services/ImageProfileService.cs b/src/Orchard.Web/Modules/Orchard.MediaProcessing/Services/ImageProfileService.cs index c002f657f..3a3a982fa 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaProcessing/Services/ImageProfileService.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaProcessing/Services/ImageProfileService.cs @@ -32,7 +32,7 @@ namespace Orchard.MediaProcessing.Services { public ImageProfilePart GetImageProfileByName(string name) { - var profileId = _cacheManager.Get("ProfileId_" + name, ctx => { + var profileId = _cacheManager.Get("ProfileId_" + name, true, ctx => { var profile = _contentManager.Query() .Where(x => x.Name == name) .Slice(0, 1) diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs index ac35578ee..adc63a0e1 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs @@ -461,7 +461,7 @@ namespace Orchard.OutputCache.Filters { private CacheSettings CacheSettings { get { - return _cacheSettings ?? (_cacheSettings = _cacheManager.Get(CacheSettings.CacheKey, context => { + return _cacheSettings ?? (_cacheSettings = _cacheManager.Get(CacheSettings.CacheKey, true, context => { context.Monitor(_signals.When(CacheSettings.CacheKey)); return new CacheSettings(_workContext.CurrentSite.As()); })); diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Services/CacheService.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Services/CacheService.cs index 542983ab6..012a494d1 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Services/CacheService.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Services/CacheService.cs @@ -99,7 +99,7 @@ namespace Orchard.OutputCache.Services { } public IEnumerable GetRouteConfigs() { - return _cacheManager.Get(RouteConfigsCacheKey, + return _cacheManager.Get(RouteConfigsCacheKey, true, ctx => { ctx.Monitor(_signals.When(RouteConfigsCacheKey)); return _repository.Fetch(c => true).Select(c => new CacheRouteConfig { RouteKey = c.RouteKey, Duration = c.Duration, GraceTime = c.GraceTime }).ToReadOnlyCollection(); diff --git a/src/Orchard.Web/Modules/Orchard.Scripting.Dlr/Services/RubyScriptExpressionEvaluator.cs b/src/Orchard.Web/Modules/Orchard.Scripting.Dlr/Services/RubyScriptExpressionEvaluator.cs index 61a283ce3..e4a1385b6 100644 --- a/src/Orchard.Web/Modules/Orchard.Scripting.Dlr/Services/RubyScriptExpressionEvaluator.cs +++ b/src/Orchard.Web/Modules/Orchard.Scripting.Dlr/Services/RubyScriptExpressionEvaluator.cs @@ -14,7 +14,7 @@ namespace Orchard.Scripting.Dlr.Services { } public object Evaluate(string expression, IEnumerable providers) { - object execContextType = _cacheManager.Get("---", ctx => (object)_scriptingManager.ExecuteExpression(@" + object execContextType = _cacheManager.Get("---", true, ctx => (object)_scriptingManager.ExecuteExpression(@" class ExecBlock def initialize(callbacks) @callbacks = callbacks @@ -38,7 +38,7 @@ class ExecContext end ExecContext ")); - var ops = _cacheManager.Get("----", ctx => (ObjectOperations)_scriptingManager.ExecuteOperation(x => x)); + var ops = _cacheManager.Get("----", true, ctx => (ObjectOperations)_scriptingManager.ExecuteOperation(x => x)); object execContext = _cacheManager.Get(expression, ctx => (object)ops.InvokeMember(execContextType, "alloc", expression)); dynamic result = ops.InvokeMember(execContext, "evaluate", new CallbackApi(this, providers)); return ConvertRubyValue(result); diff --git a/src/Orchard.Web/Modules/Orchard.Scripting/ScriptExpressionEvaluator.cs b/src/Orchard.Web/Modules/Orchard.Scripting/ScriptExpressionEvaluator.cs index b6ebf4635..7d0148717 100644 --- a/src/Orchard.Web/Modules/Orchard.Scripting/ScriptExpressionEvaluator.cs +++ b/src/Orchard.Web/Modules/Orchard.Scripting/ScriptExpressionEvaluator.cs @@ -20,7 +20,7 @@ namespace Orchard.Scripting { public Localizer T { get; set; } public object Evaluate(string expression, IEnumerable providers) { - var expr = _cacheManager.Get(expression, ctx => { + var expr = _cacheManager.Get(expression, true, ctx => { var ast = ParseExpression(expression); return new { Tree = ast, Errors = ast.GetErrors().ToList() }; }); diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Services/TagCloudService.cs b/src/Orchard.Web/Modules/Orchard.Tags/Services/TagCloudService.cs index 26dbf2c52..a05644f69 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Services/TagCloudService.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Services/TagCloudService.cs @@ -32,7 +32,7 @@ namespace Orchard.Tags.Services { public IEnumerable GetPopularTags(int buckets, string slug) { var cacheKey = "Orchard.Tags.TagCloud." + (slug ?? "") + '.' + buckets; - return _cacheManager.Get(cacheKey, + return _cacheManager.Get(cacheKey, true, ctx => { ctx.Monitor(_signals.When(TagCloudTagsChanged)); IEnumerable tagCounts; diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs b/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs index 6d8e1743a..4fc5eb6a1 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs +++ b/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs @@ -55,7 +55,7 @@ namespace Orchard.Templates.Services { } private IDictionary BuildShapeProcessors() { - return _cacheManager.Get("Template.ShapeProcessors", ctx => { + return _cacheManager.Get("Template.ShapeProcessors", true, ctx => { ctx.Monitor(_signals.When(DefaultTemplateService.TemplatesSignal)); // select all name of types which contains ShapePart diff --git a/src/Orchard/Caching/ICacheManager.cs b/src/Orchard/Caching/ICacheManager.cs index c54902eb9..785d34f0c 100644 --- a/src/Orchard/Caching/ICacheManager.cs +++ b/src/Orchard/Caching/ICacheManager.cs @@ -5,4 +5,17 @@ namespace Orchard.Caching { TResult Get(TKey key, Func, TResult> acquire); ICache GetCache(); } + + public static class CacheManagerExtensions { + public static TResult Get(this ICacheManager cacheManager, TKey key, bool lazy, Func, TResult> acquire) { + // Wrap the call in a Lazy initializer to prevent multiple processes from + // executing the same lambda in parallel. + if (lazy) { + return cacheManager.Get>(key, k => new Lazy(() => acquire(k))).Value; + } + else { + return cacheManager.Get(key, acquire); + } + } + } } diff --git a/src/Orchard/ContentManagement/DefaultContentManager.cs b/src/Orchard/ContentManagement/DefaultContentManager.cs index 7fef637aa..5ab03e3f2 100644 --- a/src/Orchard/ContentManagement/DefaultContentManager.cs +++ b/src/Orchard/ContentManagement/DefaultContentManager.cs @@ -814,7 +814,7 @@ namespace Orchard.ContentManagement { } private ContentTypeRecord AcquireContentTypeRecord(string contentType) { - var contentTypeId = _cacheManager.Get(contentType + "_Record", ctx => { + var contentTypeId = _cacheManager.Get(contentType + "_Record", true, ctx => { ctx.Monitor(_signals.When(contentType + "_Record")); var contentTypeRecord = _contentTypeRepository.Get(x => x.Name == contentType); diff --git a/src/Orchard/ContentManagement/DefaultContentQuery.cs b/src/Orchard/ContentManagement/DefaultContentQuery.cs index 468d105ef..befcd03aa 100644 --- a/src/Orchard/ContentManagement/DefaultContentQuery.cs +++ b/src/Orchard/ContentManagement/DefaultContentQuery.cs @@ -76,7 +76,7 @@ namespace Orchard.ContentManagement { } private int GetContentTypeRecordId(string contentType) { - return _cacheManager.Get(contentType + "_Record", ctx => { + return _cacheManager.Get(contentType + "_Record", true, ctx => { ctx.Monitor(_signals.When(contentType + "_Record")); var contentTypeRecord = _contentTypeRepository.Get(x => x.Name == contentType); diff --git a/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs b/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs index bc9eb0667..e1cfd57a7 100644 --- a/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs +++ b/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs @@ -37,7 +37,7 @@ namespace Orchard.DisplayManagement.Descriptors { public ILogger Logger { get; set; } public ShapeTable GetShapeTable(string themeName) { - return _cacheManager.Get(themeName ?? "", x => { + return _cacheManager.Get(themeName ?? "", true, x => { Logger.Information("Start building shape table"); var alterationSets = _parallelCacheContext.RunInParallel(_bindingStrategies, bindingStrategy => { diff --git a/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/PlacementFileParser.cs b/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/PlacementFileParser.cs index 8725ded54..9ce3454b9 100644 --- a/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/PlacementFileParser.cs +++ b/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/PlacementFileParser.cs @@ -30,7 +30,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapePlacementStrategy { public bool DisableMonitoring { get; set; } public PlacementFile Parse(string virtualPath) { - return _cacheManager.Get(virtualPath, context => { + return _cacheManager.Get(virtualPath, true, context => { if (!DisableMonitoring) { Logger.Debug("Monitoring virtual path \"{0}\"", virtualPath); diff --git a/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/ShapeTemplateBindingStrategy.cs b/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/ShapeTemplateBindingStrategy.cs index 5b04c9358..95b0c6694 100644 --- a/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/ShapeTemplateBindingStrategy.cs +++ b/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/ShapeTemplateBindingStrategy.cs @@ -77,7 +77,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy { var pathContexts = harvesterInfos.SelectMany(harvesterInfo => harvesterInfo.subPaths.Select(subPath => { var basePath = Path.Combine(extensionDescriptor.Location, extensionDescriptor.Id).Replace(Path.DirectorySeparatorChar, '/'); var virtualPath = Path.Combine(basePath, subPath).Replace(Path.DirectorySeparatorChar, '/'); - var fileNames = _cacheManager.Get(virtualPath, ctx => { + var fileNames = _cacheManager.Get(virtualPath, true, ctx => { if (!_virtualPathProvider.DirectoryExists(virtualPath)) return new List(); diff --git a/src/Orchard/Environment/Extensions/Compilers/DefaultProjectFileParser.cs b/src/Orchard/Environment/Extensions/Compilers/DefaultProjectFileParser.cs index 01a717b12..08adf43a1 100644 --- a/src/Orchard/Environment/Extensions/Compilers/DefaultProjectFileParser.cs +++ b/src/Orchard/Environment/Extensions/Compilers/DefaultProjectFileParser.cs @@ -23,7 +23,7 @@ namespace Orchard.Environment.Extensions.Compilers { public bool DisableMonitoring { get; set; } public ProjectFileDescriptor Parse(string virtualPath) { - return _cacheManager.Get(virtualPath, + return _cacheManager.Get(virtualPath, true, ctx => { if (!DisableMonitoring) { Logger.Debug("Monitoring virtual path \"{0}\"", virtualPath); diff --git a/src/Orchard/Environment/Extensions/ExtensionManager.cs b/src/Orchard/Environment/Extensions/ExtensionManager.cs index 4dc8c02d3..40092fd21 100644 --- a/src/Orchard/Environment/Extensions/ExtensionManager.cs +++ b/src/Orchard/Environment/Extensions/ExtensionManager.cs @@ -45,7 +45,7 @@ namespace Orchard.Environment.Extensions { } public IEnumerable AvailableExtensions() { - return _cacheManager.Get("AvailableExtensions", ctx => + return _cacheManager.Get("AvailableExtensions", true, ctx => _parallelCacheContext .RunInParallel(_folders, folder => folder.AvailableExtensions().ToList()) .SelectMany(descriptors => descriptors) @@ -53,7 +53,7 @@ namespace Orchard.Environment.Extensions { } public IEnumerable AvailableFeatures() { - return _cacheManager.Get("AvailableFeatures", ctx => + return _cacheManager.Get("AvailableFeatures", true, ctx => AvailableExtensions() .SelectMany(ext => ext.Features) .OrderByDependenciesAndPriorities(HasDependency, GetPriority) @@ -93,7 +93,7 @@ namespace Orchard.Environment.Extensions { var result = _parallelCacheContext - .RunInParallel(featureDescriptors, descriptor => _cacheManager.Get(descriptor.Id, ctx => LoadFeature(descriptor))) + .RunInParallel(featureDescriptors, descriptor => _cacheManager.Get(descriptor.Id, true, ctx => LoadFeature(descriptor))) .ToArray(); Logger.Information("Done loading features"); @@ -107,7 +107,7 @@ namespace Orchard.Environment.Extensions { ExtensionEntry extensionEntry; try { - extensionEntry = _cacheManager.Get(extensionId, ctx => { + extensionEntry = _cacheManager.Get(extensionId, true, ctx => { var entry = BuildEntry(extensionDescriptor); if (entry != null) { ctx.Monitor(_asyncTokenProvider.GetToken(monitor => { diff --git a/src/Orchard/Environment/Extensions/Folders/ExtensionHarvester.cs b/src/Orchard/Environment/Extensions/Folders/ExtensionHarvester.cs index 38215b366..2a7bfbafb 100644 --- a/src/Orchard/Environment/Extensions/Folders/ExtensionHarvester.cs +++ b/src/Orchard/Environment/Extensions/Folders/ExtensionHarvester.cs @@ -56,7 +56,7 @@ namespace Orchard.Environment.Extensions.Folders { private IEnumerable HarvestExtensions(string path, string extensionType, string manifestName, bool manifestIsOptional) { string key = string.Format("{0}-{1}-{2}", path, manifestName, extensionType); - return _cacheManager.Get(key, ctx => { + return _cacheManager.Get(key, true, ctx => { if (!DisableMonitoring) { Logger.Debug("Monitoring virtual path \"{0}\"", path); ctx.Monitor(_webSiteFolder.WhenPathChanges(path)); @@ -135,7 +135,7 @@ namespace Orchard.Environment.Extensions.Folders { } private ExtensionDescriptor GetExtensionDescriptor(string locationPath, string extensionId, string extensionType, string manifestPath, bool manifestIsOptional) { - return _cacheManager.Get(manifestPath, context => { + return _cacheManager.Get(manifestPath, true, context => { if (!DisableMonitoring) { Logger.Debug("Monitoring virtual path \"{0}\"", manifestPath); context.Monitor(_webSiteFolder.WhenPathChanges(manifestPath)); diff --git a/src/Orchard/Environment/IAssemblyNameResolver.cs b/src/Orchard/Environment/IAssemblyNameResolver.cs index f97631719..78d809ab7 100644 --- a/src/Orchard/Environment/IAssemblyNameResolver.cs +++ b/src/Orchard/Environment/IAssemblyNameResolver.cs @@ -37,7 +37,7 @@ namespace Orchard.Environment { public string Resolve(string shortName) { // A few common .net framework assemblies are referenced by the Orchard.Framework assembly. // Look into those to see if we can find the assembly we are looking for. - var orchardFrameworkReferences = _cacheManager.Get(typeof(IAssemblyLoader), ctx => + var orchardFrameworkReferences = _cacheManager.Get(typeof(IAssemblyLoader), true, ctx => ctx.Key.Assembly .GetReferencedAssemblies() .GroupBy(n => AssemblyLoaderExtensions.ExtractAssemblyShortName(n.FullName), StringComparer.OrdinalIgnoreCase) diff --git a/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs b/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs index de9c05869..ace5674fe 100644 --- a/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs +++ b/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs @@ -34,7 +34,7 @@ namespace Orchard.FileSystems.Dependencies { } public IEnumerable LoadDescriptors() { - return _cacheManager.Get(PersistencePath, + return _cacheManager.Get(PersistencePath, true, ctx => { _appDataFolder.CreateDirectory(BasePath); diff --git a/src/Orchard/FileSystems/Dependencies/DefaultExtensionDependenciesManager.cs b/src/Orchard/FileSystems/Dependencies/DefaultExtensionDependenciesManager.cs index 1afd04077..afde10403 100644 --- a/src/Orchard/FileSystems/Dependencies/DefaultExtensionDependenciesManager.cs +++ b/src/Orchard/FileSystems/Dependencies/DefaultExtensionDependenciesManager.cs @@ -65,7 +65,7 @@ namespace Orchard.FileSystems.Dependencies { } public IEnumerable LoadDescriptors() { - return _cacheManager.Get(PersistencePath, ctx => { + return _cacheManager.Get(PersistencePath, true, ctx => { _appDataFolder.CreateDirectory(BasePath); if (!DisableMonitoring) { diff --git a/src/Orchard/Localization/Services/DefaultCultureManager.cs b/src/Orchard/Localization/Services/DefaultCultureManager.cs index 9026e4acb..19ffa05b8 100644 --- a/src/Orchard/Localization/Services/DefaultCultureManager.cs +++ b/src/Orchard/Localization/Services/DefaultCultureManager.cs @@ -26,7 +26,7 @@ namespace Orchard.Localization.Services { } public IEnumerable ListCultures() { - return _cacheManager.Get("Cultures", context => { + return _cacheManager.Get("Cultures", true, context => { context.Monitor(_signals.When("culturesChanged")); return _cultureRepository.Table.Select(o => o.Culture).ToList(); diff --git a/src/Orchard/Localization/Services/DefaultLocalizedStringManager.cs b/src/Orchard/Localization/Services/DefaultLocalizedStringManager.cs index cb9516399..e0a2a29de 100644 --- a/src/Orchard/Localization/Services/DefaultLocalizedStringManager.cs +++ b/src/Orchard/Localization/Services/DefaultLocalizedStringManager.cs @@ -90,7 +90,7 @@ namespace Orchard.Localization.Services { // Cache entry will be invalidated any time the directories hosting // the .po files are modified. private CultureDictionary LoadCulture(string culture) { - return _cacheManager.Get(culture, ctx => { + return _cacheManager.Get(culture, true, ctx => { ctx.Monitor(_signals.When("culturesChanged")); return new CultureDictionary { CultureName = culture, From 60798f93468d84fc6a48725ca30d996aab59c0e4 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Tue, 8 Sep 2015 17:09:53 -0700 Subject: [PATCH 24/25] Fixing TokenManagerTests --- .../Modules/Orchard.Tokens/Tests/TokenManagerTests.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenManagerTests.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenManagerTests.cs index 341e5ed37..073442bb9 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenManagerTests.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenManagerTests.cs @@ -29,10 +29,11 @@ namespace Orchard.Tokens.Tests { [Test] public void TestDescribe() { var allTokens = _tokenManager.Describe(null); - Assert.That(allTokens.Count(), Is.EqualTo(3)); + Assert.That(allTokens.Count(), Is.EqualTo(4)); Assert.That(allTokens.Any(d => d.Target == "Site")); Assert.That(allTokens.Any(d => d.Target == "User")); Assert.That(allTokens.Any(d => d.Target == "Date")); + Assert.That(allTokens.Any(d => d.Target == "Users")); var tokens = allTokens.Single(d => d.Target == "Site").Tokens; Assert.That(string.Join(",", tokens.Select(td => td.Target)), Is.EqualTo("Site,Site,Site,Site")); @@ -59,7 +60,7 @@ namespace Orchard.Tokens.Tests { [Test] public void TestDescribeFilter() { var tokenDescriptors = _tokenManager.Describe(null); - Assert.That(tokenDescriptors.Count(), Is.EqualTo(3)); + Assert.That(tokenDescriptors.Count(), Is.EqualTo(4)); tokenDescriptors = _tokenManager.Describe(new[] { "Site" }); Assert.That(tokenDescriptors.Count(), Is.EqualTo(1)); Assert.That(tokenDescriptors.First().Target, Is.EqualTo("Site")); From e8f0ba6ec72b0ee48e953befa6676057259f1b3d Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Tue, 8 Sep 2015 17:12:44 -0700 Subject: [PATCH 25/25] Fixing RecipeManagerTests --- .../Recipes/Services/RecipeManagerTests.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Orchard.Tests.Modules/Recipes/Services/RecipeManagerTests.cs b/src/Orchard.Tests.Modules/Recipes/Services/RecipeManagerTests.cs index c5d3902bd..9d58c475d 100644 --- a/src/Orchard.Tests.Modules/Recipes/Services/RecipeManagerTests.cs +++ b/src/Orchard.Tests.Modules/Recipes/Services/RecipeManagerTests.cs @@ -98,23 +98,23 @@ namespace Orchard.Tests.Modules.Recipes.Services { [Test] public void HarvestRecipesFailsToFindRecipesWhenCalledWithNotExistingExtension() { - var recipes = (List) _recipeHarvester.HarvestRecipes("cantfindme"); + var recipes = _recipeHarvester.HarvestRecipes("cantfindme"); - Assert.That(recipes.Count, Is.EqualTo(0)); + Assert.That(recipes.Count(), Is.EqualTo(0)); } [Test] public void HarvestRecipesShouldHarvestRecipeXmlFiles() { - var recipes = (List)_recipeHarvester.HarvestRecipes("Sample1"); - Assert.That(recipes.Count, Is.EqualTo(1)); + var recipes = _recipeHarvester.HarvestRecipes("Sample1"); + Assert.That(recipes.Count(), Is.EqualTo(1)); } [Test] public void ParseRecipeLoadsRecipeMetaDataIntoModel() { - var recipes = (List) _recipeHarvester.HarvestRecipes("Sample1"); - Assert.That(recipes.Count, Is.EqualTo(1)); + var recipes = _recipeHarvester.HarvestRecipes("Sample1"); + Assert.That(recipes.Count(), Is.EqualTo(1)); - var sampleRecipe = recipes[0]; + var sampleRecipe = recipes.First(); Assert.That(sampleRecipe.Name, Is.EqualTo("cms")); Assert.That(sampleRecipe.Description, Is.EqualTo("a sample Orchard recipe describing a cms")); Assert.That(sampleRecipe.Author, Is.EqualTo("orchard"));