From 0b8260f3fa800dcbd2d6238f88301fbadf8a8c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Ros?= Date: Mon, 20 Apr 2015 21:11:09 -0700 Subject: [PATCH 01/73] Create README.md --- README.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000..aca411162 --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +# Orchard +Orchard is a free, open source, community-focused Content Management System built on the ASP.NET MVC platform. + +## About The Orchard Project + +#### Please visit our website at http://orchardproject.net for the most current information about this project. + +Orchard is a free, open source, community-focused project aimed at delivering applications and reusable components +on the ASP.NET platform. It will create shared components for building ASP.NET applications and extensions, and +specific applications that leverage these components to meet the needs of end-users, scripters, and developers. +Additionally, we seek to create partnerships with existing application authors to help them achieve their goals. +Orchard is delivered under the [.NET Foundation](http://www.dotnetfoundation.org/). It is licensed under a +[New BSD license](http://www.opensource.org/licenses/bsd-license.php), which is approved by the OSI. The intended +output of the Orchard project is three-fold: + +* Individual .NET-based applications that appeal to end-users, scripters, and developers +* A set of re-usable components that makes it easy to build such applications +* A vibrant community to help define these applications and extensions +In the near term, the Orchard project is focused on delivering a .NET-based CMS application that will allow users +to rapidly create content-driven Websites, and an extensibility framework that will allow developers and customizers to provide additional functionality through modules and themes. You can learn more about the project on the [url:Orchard Project Website|http://www.orchardproject.net]. + +## Project Status +Orchard is currently in version 1.8.1. We invite participation by the developer community in shaping the project’s direction, so that we can publicly validate our designs and development approach. +Our 1.8.1 release is available from our Downloads page, and is easy to [url: Install Orchard using the Web Platform Installer | http://www.orchardproject.net/docs/Installing-Orchard.ashx]. We encourage interested developers to check out the source code on the Orchard Github site and get involved with the project. + +* [Download the latest release](https://github.com/OrchardCMS/Orchard/releases) +* [Feature roadmap](http://www.orchardproject.net/docs/feature-roadmap.ashx) +* [Docs and designs/specs](http://www.orchardproject.net/docs) +* [About us](http://www.orchardproject.net/about) +* [Contact us](mailto:ofeedbk@microsoft.com) + +## How To Get Involved +We hope that by engaging with the community in the very early stages of the project that we will be able to shape Orchard into a valuable set of tools and applications for the community. The Orchard team is committed to open community participation and accepts code contributions today. We encourage community participation at all levels from general project feedback to bug fixes and patches. + +* [Check out the code](https://github.com/OrchardCMS/Orchard) +* [Check out the docs](http://orchardproject.net/docs) +* [Find and file a bug](https://github.com/OrchardCMS/Orchard/issues) +* [Propose a feature idea](http://orchard.uservoice.com) +* [Ask and answer questions](http://www.orchardproject.net/discussions) +* [Participate in forum discussions](http://orchard.codeplex.com/discussions) +* [Submit a patch](http://www.orchardproject.net/docs/Contributing-patches.ashx) +* [Send us feedback](mailto:ofeedbk@microsoft.com) From 1c1ba30a8ca78250654f1d17cdaa18778be76b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Ros?= Date: Wed, 22 Apr 2015 15:44:07 -0700 Subject: [PATCH 02/73] Fixing links in README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index aca411162..7d255e283 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,11 @@ output of the Orchard project is three-fold: * A set of re-usable components that makes it easy to build such applications * A vibrant community to help define these applications and extensions In the near term, the Orchard project is focused on delivering a .NET-based CMS application that will allow users -to rapidly create content-driven Websites, and an extensibility framework that will allow developers and customizers to provide additional functionality through modules and themes. You can learn more about the project on the [url:Orchard Project Website|http://www.orchardproject.net]. +to rapidly create content-driven Websites, and an extensibility framework that will allow developers and customizers to provide additional functionality through modules and themes. You can learn more about the project on the [Orchard Project Website](http://www.orchardproject.net). ## Project Status Orchard is currently in version 1.8.1. We invite participation by the developer community in shaping the project’s direction, so that we can publicly validate our designs and development approach. -Our 1.8.1 release is available from our Downloads page, and is easy to [url: Install Orchard using the Web Platform Installer | http://www.orchardproject.net/docs/Installing-Orchard.ashx]. We encourage interested developers to check out the source code on the Orchard Github site and get involved with the project. +Our 1.8.1 release is available from our Downloads page, and is easy to [Install Orchard using the Web Platform Installer](http://www.orchardproject.net/docs/Installing-Orchard.ashx). We encourage interested developers to check out the source code on the Orchard Github site and get involved with the project. * [Download the latest release](https://github.com/OrchardCMS/Orchard/releases) * [Feature roadmap](http://www.orchardproject.net/docs/feature-roadmap.ashx) From c91ff877739aeb27cb4906001eddd7146822e5b3 Mon Sep 17 00:00:00 2001 From: Kees Damen Date: Fri, 24 Apr 2015 23:15:46 +0200 Subject: [PATCH 03/73] Fixed the Orchard behavior of passing windows credentials to e-mail server when no credentials where entered. Added an option to the smptsettings configuration to explicitly configure windows authentication. This fixes bugs #2536 and #5024. --- .../Controllers/EmailAdminController.cs | 2 ++ .../Handlers/SmtpSettingsPartHandler.cs | 2 -- .../Orchard.Email/Models/SmtpSettingsPart.cs | 6 ++++ .../Orchard.Email/Orchard.Email.csproj | 22 ++++++------ .../Services/SmtpMessageChannel.cs | 2 +- .../EditorTemplates/Parts/SmtpSettings.cshtml | 35 ++++++++++++++----- 6 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Email/Controllers/EmailAdminController.cs b/src/Orchard.Web/Modules/Orchard.Email/Controllers/EmailAdminController.cs index 6aca6ba30..2eeab85c6 100644 --- a/src/Orchard.Web/Modules/Orchard.Email/Controllers/EmailAdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Email/Controllers/EmailAdminController.cs @@ -41,6 +41,7 @@ namespace Orchard.Email.Controllers { smtpSettings.Port = testSettings.Port; smtpSettings.EnableSsl = testSettings.EnableSsl; smtpSettings.RequireCredentials = testSettings.RequireCredentials; + smtpSettings.UseDefaultCredentials = testSettings.UseDefaultCredentials; smtpSettings.UserName = testSettings.UserName; smtpSettings.Password = testSettings.Password; @@ -97,6 +98,7 @@ namespace Orchard.Email.Controllers { public int Port { get; set; } public bool EnableSsl { get; set; } public bool RequireCredentials { get; set; } + public bool UseDefaultCredentials { get; set; } public string UserName { get; set; } public string Password { get; set; } public string To { get; set; } diff --git a/src/Orchard.Web/Modules/Orchard.Email/Handlers/SmtpSettingsPartHandler.cs b/src/Orchard.Web/Modules/Orchard.Email/Handlers/SmtpSettingsPartHandler.cs index 9019fda20..50ca2593a 100644 --- a/src/Orchard.Web/Modules/Orchard.Email/Handlers/SmtpSettingsPartHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Email/Handlers/SmtpSettingsPartHandler.cs @@ -1,6 +1,5 @@ using System; using System.Text; -using JetBrains.Annotations; using Orchard.ContentManagement; using Orchard.Email.Models; using Orchard.ContentManagement.Handlers; @@ -10,7 +9,6 @@ using Orchard.Security; using System.Configuration; namespace Orchard.Email.Handlers { - [UsedImplicitly] public class SmtpSettingsPartHandler : ContentHandler { private readonly IEncryptionService _encryptionService; diff --git a/src/Orchard.Web/Modules/Orchard.Email/Models/SmtpSettingsPart.cs b/src/Orchard.Web/Modules/Orchard.Email/Models/SmtpSettingsPart.cs index 27ea30d8e..cf4561271 100644 --- a/src/Orchard.Web/Modules/Orchard.Email/Models/SmtpSettingsPart.cs +++ b/src/Orchard.Web/Modules/Orchard.Email/Models/SmtpSettingsPart.cs @@ -41,6 +41,12 @@ namespace Orchard.Email.Models { set { this.Store(x => x.RequireCredentials, value); } } + public bool UseDefaultCredentials + { + get { return this.Retrieve(x => x.UseDefaultCredentials); } + set { this.Store(x => x.UseDefaultCredentials, value); } + } + public string UserName { get { return this.Retrieve(x => x.UserName); } set { this.Store(x => x.UserName, value); } diff --git a/src/Orchard.Web/Modules/Orchard.Email/Orchard.Email.csproj b/src/Orchard.Web/Modules/Orchard.Email/Orchard.Email.csproj index e7acd2b5c..c60a0eed5 100644 --- a/src/Orchard.Web/Modules/Orchard.Email/Orchard.Email.csproj +++ b/src/Orchard.Web/Modules/Orchard.Email/Orchard.Email.csproj @@ -141,24 +141,24 @@ - - $(ProjectDir)\..\Manifests - - diff --git a/src/Orchard.Web/Modules/Orchard.Email/Services/SmtpMessageChannel.cs b/src/Orchard.Web/Modules/Orchard.Email/Services/SmtpMessageChannel.cs index dbb98fd6a..0ab833e6b 100644 --- a/src/Orchard.Web/Modules/Orchard.Email/Services/SmtpMessageChannel.cs +++ b/src/Orchard.Web/Modules/Orchard.Email/Services/SmtpMessageChannel.cs @@ -133,7 +133,7 @@ namespace Orchard.Email.Services { } var smtpClient = new SmtpClient { - UseDefaultCredentials = !_smtpSettings.RequireCredentials, + UseDefaultCredentials = _smtpSettings.RequireCredentials && _smtpSettings.UseDefaultCredentials }; if (!smtpClient.UseDefaultCredentials && !String.IsNullOrWhiteSpace(_smtpSettings.UserName)) { diff --git a/src/Orchard.Web/Modules/Orchard.Email/Views/EditorTemplates/Parts/SmtpSettings.cshtml b/src/Orchard.Web/Modules/Orchard.Email/Views/EditorTemplates/Parts/SmtpSettings.cshtml index 2f2653098..622156159 100644 --- a/src/Orchard.Web/Modules/Orchard.Email/Views/EditorTemplates/Parts/SmtpSettings.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Email/Views/EditorTemplates/Parts/SmtpSettings.cshtml @@ -35,18 +35,32 @@ @Html.ValidationMessage("RequireCredentials", "*") +
- - @Html.TextBoxFor(m => m.UserName, new { @class = "text" }) - @Html.ValidationMessage("UserName", "*") - @T("The username for authentication.") + @Html.RadioButtonFor(m => m.UseDefaultCredentials, false) + + @Html.ValidationMessage("UseDefaultCredentials", "*")
- - @Html.TextBoxFor(m => m.Password, new { type = "password", @class = "text medium" }) - @Html.ValidationMessage("Password", "*") - @T("The password for authentication.") +
+ + @Html.TextBoxFor(m => m.UserName, new { @class = "text" }) + @Html.ValidationMessage("UserName", "*") + @T("The username for authentication.") +
+
+ + @Html.TextBoxFor(m => m.Password, new { type = "password", @class = "text medium" }) + @Html.ValidationMessage("Password", "*") + @T("The password for authentication.") +
+
+
+ @Html.RadioButtonFor(m => m.UseDefaultCredentials, true, new { id = "smtpUseDefaultCredentials" }) + + @Html.ValidationMessage("UseCustomCredentials", "*") + @T("When this option is checked, the aplication pool or host-process identity is used to authenticate with the mail server. ")
@@ -80,7 +94,8 @@ - @using (Script.Foot()) { + @using (Script.Foot()) + { + // replaces a specific query parameter in the given url + function replaceQueryString(url, param, value) { + value = encodeURIComponent(value); + var re = new RegExp("([?|&])" + param + "=.*?(&|$)", "i"); + if (url.match(re)) + return url.replace(re, '$1' + param + "=" + value + '$2'); + else + return url + '&' + param + "=" + value; + } + + //]]> + } \ No newline at end of file From fa3f1cbc70d7763710ff24659e84b2a02321fb0b Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 6 May 2015 21:38:41 +0200 Subject: [PATCH 39/73] Added NumericFieldBinding. --- .../Bindings/NumericFieldBindings.cs | 13 +++++++++++++ .../Orchard.DynamicForms.csproj | 1 + 2 files changed, 14 insertions(+) create mode 100644 src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/NumericFieldBindings.cs diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/NumericFieldBindings.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/NumericFieldBindings.cs new file mode 100644 index 000000000..d9e40402e --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/NumericFieldBindings.cs @@ -0,0 +1,13 @@ +using Orchard.ContentManagement; +using Orchard.DynamicForms.Services; +using Orchard.DynamicForms.Services.Models; +using Orchard.Fields.Fields; + +namespace Orchard.DynamicForms.Bindings { + public class NumericFieldBindings : Component, IBindingProvider { + public void Describe(BindingDescribeContext context) { + context.For() + .Binding("Value", (contentItem, field, s) => field.Value = XmlHelper.Parse(s)); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Orchard.DynamicForms.csproj b/src/Orchard.Web/Modules/Orchard.DynamicForms/Orchard.DynamicForms.csproj index 097b3f2e3..8f2d88c6b 100644 --- a/src/Orchard.Web/Modules/Orchard.DynamicForms/Orchard.DynamicForms.csproj +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Orchard.DynamicForms.csproj @@ -166,6 +166,7 @@ + From 635abd7456470c1ff6d7398963b01bef684bfa1e Mon Sep 17 00:00:00 2001 From: Daniel Stolt Date: Thu, 7 May 2015 14:16:56 +0200 Subject: [PATCH 40/73] Fixed unit tests not being discovered due to CopyLocal=false on core references. Having CopyLocal=false on references to Orchard.Core and Orchard.Framework in unit test projects prevented VS from discovering unit tests (at least when using the NUnit Test Adapter for Visual Studio). This change resets CopyLocal=true for these references in all unit test projects. --- src/Orchard.Specs/Orchard.Specs.csproj | 4 ++-- src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj | 4 ++-- src/Orchard.Tests/Orchard.Framework.Tests.csproj | 4 ++-- src/Orchard.Web.Tests/Orchard.Web.Tests.csproj | 2 +- .../Tests/Orchard.Projections.Tests.csproj | 4 ++-- .../Orchard.Tokens/Tests/Orchard.Tokens.Tests.csproj | 8 +++++--- 6 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Orchard.Specs/Orchard.Specs.csproj b/src/Orchard.Specs/Orchard.Specs.csproj index 8199edda6..2415be3b0 100644 --- a/src/Orchard.Specs/Orchard.Specs.csproj +++ b/src/Orchard.Specs/Orchard.Specs.csproj @@ -426,7 +426,7 @@ {9916839C-39FC-4CEB-A5AF-89CA7E87119F} Orchard.Core - false + True {D10AD48F-407D-4DB5-A328-173EC7CB010F} @@ -447,7 +447,7 @@ {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} Orchard.Framework - false + True {33B1BC8D-E292-4972-A363-22056B207156} diff --git a/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj b/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj index 23b9ef454..c0b316f4e 100644 --- a/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj +++ b/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj @@ -205,7 +205,7 @@ {9916839C-39FC-4CEB-A5AF-89CA7E87119F} Orchard.Core - false + True {D5D447D7-EF8E-43A6-B9A4-3B025DD9F45D} @@ -302,7 +302,7 @@ {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} Orchard.Framework - false + True diff --git a/src/Orchard.Tests/Orchard.Framework.Tests.csproj b/src/Orchard.Tests/Orchard.Framework.Tests.csproj index 8f62cd7b0..48ad9a1ea 100644 --- a/src/Orchard.Tests/Orchard.Framework.Tests.csproj +++ b/src/Orchard.Tests/Orchard.Framework.Tests.csproj @@ -331,12 +331,12 @@ {9916839C-39FC-4CEB-A5AF-89CA7E87119F} Orchard.Core - false + True {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} Orchard.Framework - false + True diff --git a/src/Orchard.Web.Tests/Orchard.Web.Tests.csproj b/src/Orchard.Web.Tests/Orchard.Web.Tests.csproj index a0b1b8124..b547113f9 100644 --- a/src/Orchard.Web.Tests/Orchard.Web.Tests.csproj +++ b/src/Orchard.Web.Tests/Orchard.Web.Tests.csproj @@ -96,7 +96,7 @@ {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} Orchard.Framework - false + True diff --git a/src/Orchard.Web/Modules/Orchard.Projections/Tests/Orchard.Projections.Tests.csproj b/src/Orchard.Web/Modules/Orchard.Projections/Tests/Orchard.Projections.Tests.csproj index 7e2d6a6b7..2b2dd6f3e 100644 --- a/src/Orchard.Web/Modules/Orchard.Projections/Tests/Orchard.Projections.Tests.csproj +++ b/src/Orchard.Web/Modules/Orchard.Projections/Tests/Orchard.Projections.Tests.csproj @@ -82,12 +82,12 @@ {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} Orchard.Framework - false + True {9916839C-39FC-4CEB-A5AF-89CA7E87119F} Orchard.Core - false + True {5531E894-D259-45A3-AA61-26DBE720C1CE} diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/Orchard.Tokens.Tests.csproj b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/Orchard.Tokens.Tests.csproj index 9028e4573..52c78d2e9 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/Orchard.Tokens.Tests.csproj +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/Orchard.Tokens.Tests.csproj @@ -42,7 +42,9 @@ ..\..\..\..\..\lib\nunit\nunit.framework.dll - + + False + @@ -65,12 +67,12 @@ {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} Orchard.Framework - false + True {9916839C-39FC-4CEB-A5AF-89CA7E87119F} Orchard.Core - false + True {6F759635-13D7-4E94-BCC9-80445D63F117} From 9491a5750bdec559a9fffe59fe63431c40b90b03 Mon Sep 17 00:00:00 2001 From: Daniel Stolt Date: Thu, 7 May 2015 16:44:41 +0200 Subject: [PATCH 41/73] Added support for era names to date formatting/parsing framework (fixes failing unit tests on Windows 10). --- .../LocalizationDateTimeFormatProvider.cs | 33 +++++++- .../Services/CultureDateTimeFormatProvider.cs | 14 +++- .../Services/DefaultDateFormatter.cs | 84 ++++++++++--------- .../Services/IDateTimeFormatProvider.cs | 17 +++- 4 files changed, 106 insertions(+), 42 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Localization/Providers/LocalizationDateTimeFormatProvider.cs b/src/Orchard.Web/Modules/Orchard.Localization/Providers/LocalizationDateTimeFormatProvider.cs index 3cbca9c0a..cdb316a42 100644 --- a/src/Orchard.Web/Modules/Orchard.Localization/Providers/LocalizationDateTimeFormatProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Localization/Providers/LocalizationDateTimeFormatProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Orchard.Environment.Extensions; using Orchard.Localization.Services; @@ -171,6 +172,36 @@ namespace Orchard.Localization.Providers { return new string[] { "AM", "PM" }; } - } + } + + public string GetEraName(int era) { + var t = T("A.D.;A.D.").Text; + var parts = t.Split(';'); + if (parts.Length >= era + 1) { + return parts[era]; + } + + return null; + } + + public string GetShortEraName(int era) { + var t = T("AD;AD").Text; + var parts = t.Split(';'); + if (parts.Length >= era + 1) { + return parts[era]; + } + + return null; + } + + public int GetEra(string eraName) { + var t = T("AD;AD").Text; + var parts = t.ToLowerInvariant().Split(';'); + if (parts.Contains(eraName.ToLowerInvariant())) { + return parts.ToList().IndexOf(eraName.ToLowerInvariant()); + } + + throw new ArgumentOutOfRangeException("eraName"); + } } } \ No newline at end of file diff --git a/src/Orchard/Localization/Services/CultureDateTimeFormatProvider.cs b/src/Orchard/Localization/Services/CultureDateTimeFormatProvider.cs index 1ffda8e2d..5bb1c1139 100644 --- a/src/Orchard/Localization/Services/CultureDateTimeFormatProvider.cs +++ b/src/Orchard/Localization/Services/CultureDateTimeFormatProvider.cs @@ -177,6 +177,18 @@ namespace Orchard.Localization.Services { return new[] { DateTimeFormat.AMDesignator, DateTimeFormat.PMDesignator }; } } + + public string GetEraName(int era) { + return DateTimeFormat.GetEraName(era); + } + + public string GetShortEraName(int era) { + return DateTimeFormat.GetAbbreviatedEraName(era); + } + + public int GetEra(string eraName) { + return DateTimeFormat.GetEra(eraName); + } protected virtual DateTimeFormatInfo DateTimeFormat { get { @@ -230,6 +242,6 @@ namespace Orchard.Localization.Services { return _calendarManager.GetCalendarByName(workContext.CurrentCalendar); return CurrentCulture.Calendar; } - } + } } } \ No newline at end of file diff --git a/src/Orchard/Localization/Services/DefaultDateFormatter.cs b/src/Orchard/Localization/Services/DefaultDateFormatter.cs index 696f1ab29..03193d2ba 100644 --- a/src/Orchard/Localization/Services/DefaultDateFormatter.cs +++ b/src/Orchard/Localization/Services/DefaultDateFormatter.cs @@ -110,11 +110,11 @@ namespace Orchard.Localization.Services { int twoDigitYear, hour12, offsetHours, offsetMinutes; bool isPm; - string monthName, monthNameShort, monthNameGenitive, monthNameShortGenitive, dayName, dayNameShort, amPm, amPmShort, timeZone, offsetSign, fraction1Zero, fraction2Zero, fraction3Zero, fraction1Digit, fraction2Digit, fraction3Digit; - GetDateFormatValues(parts.Date, calendar, out twoDigitYear, out monthName, out monthNameShort, out monthNameGenitive, out monthNameShortGenitive, out dayName, out dayNameShort); + string monthName, monthNameShort, monthNameGenitive, monthNameShortGenitive, dayName, dayNameShort, eraName, eraNameShort, amPm, amPmShort, timeZone, offsetSign, fraction1Zero, fraction2Zero, fraction3Zero, fraction1Digit, fraction2Digit, fraction3Digit; + GetDateFormatValues(parts.Date, calendar, out twoDigitYear, out monthName, out monthNameShort, out monthNameGenitive, out monthNameShortGenitive, out dayName, out dayNameShort, out eraName, out eraNameShort); GetTimeFormatValues(parts.Time, out isPm, out hour12, out amPm, out amPmShort, out timeZone, out offsetSign, out offsetHours, out offsetMinutes, out fraction1Zero, out fraction2Zero, out fraction3Zero, out fraction1Digit, out fraction2Digit, out fraction3Digit); - return String.Format(formatString, parts.Date.Year, twoDigitYear, parts.Date.Month, monthName, monthNameShort, monthNameGenitive, monthNameShortGenitive, parts.Date.Day, dayName, dayNameShort, parts.Time.Hour, hour12, parts.Time.Minute, parts.Time.Second, fraction1Zero, fraction2Zero, fraction3Zero, fraction1Digit, fraction2Digit, fraction3Digit, amPm, amPmShort, timeZone, offsetSign, offsetHours, offsetMinutes); + return String.Format(formatString, parts.Date.Year, twoDigitYear, parts.Date.Month, monthName, monthNameShort, monthNameGenitive, monthNameShortGenitive, parts.Date.Day, dayName, dayNameShort, eraName, eraNameShort, parts.Time.Hour, hour12, parts.Time.Minute, parts.Time.Second, fraction1Zero, fraction2Zero, fraction3Zero, fraction1Digit, fraction2Digit, fraction3Digit, amPm, amPmShort, timeZone, offsetSign, offsetHours, offsetMinutes); } public virtual string FormatDate(DateParts parts) { @@ -129,10 +129,10 @@ namespace Orchard.Localization.Services { var calendar = CurrentCalendar; int twoDigitYear; - string monthName, monthNameShort, monthNameGenitive, monthNameShortGenitive, dayName, dayNameShort; - GetDateFormatValues(parts, calendar, out twoDigitYear, out monthName, out monthNameShort, out monthNameGenitive, out monthNameShortGenitive, out dayName, out dayNameShort); + string monthName, monthNameShort, monthNameGenitive, monthNameShortGenitive, dayName, dayNameShort, eraName, eraNameShort; + GetDateFormatValues(parts, calendar, out twoDigitYear, out monthName, out monthNameShort, out monthNameGenitive, out monthNameShortGenitive, out dayName, out dayNameShort, out eraName, out eraNameShort); - return String.Format(formatString, parts.Year, twoDigitYear, parts.Month, monthName, monthNameShort, monthNameGenitive, monthNameShortGenitive, parts.Day, dayName, dayNameShort); + return String.Format(formatString, parts.Year, twoDigitYear, parts.Month, monthName, monthNameShort, monthNameGenitive, monthNameShortGenitive, parts.Day, dayName, dayNameShort, eraName, eraNameShort); } public virtual string FormatTime(TimeParts parts) { @@ -148,7 +148,7 @@ namespace Orchard.Localization.Services { string amPm, amPmShort, timeZone, offsetSign, fraction1Zero, fraction2Zero, fraction3Zero, fraction1Digit, fraction2Digit, fraction3Digit; GetTimeFormatValues(parts, out isPm, out hour12, out amPm, out amPmShort, out timeZone, out offsetSign, out offsetHours, out offsetMinutes, out fraction1Zero, out fraction2Zero, out fraction3Zero, out fraction1Digit, out fraction2Digit, out fraction3Digit); - return String.Format(formatString, null, null, null, null, null, null, null, null, null, null, parts.Hour, hour12, parts.Minute, parts.Second, fraction1Zero, fraction2Zero, fraction3Zero, fraction1Digit, fraction2Digit, fraction3Digit, amPm, amPmShort, timeZone, offsetSign, offsetHours, offsetMinutes); + return String.Format(formatString, null, null, null, null, null, null, null, null, null, null, null, null, parts.Hour, hour12, parts.Minute, parts.Second, fraction1Zero, fraction2Zero, fraction3Zero, fraction1Digit, fraction2Digit, fraction3Digit, amPm, amPmShort, timeZone, offsetSign, offsetHours, offsetMinutes); } protected virtual DateTimeParts? TryParseDateTime(string dateTimeString, string format, IDictionary replacements) { @@ -290,7 +290,7 @@ namespace Orchard.Localization.Services { return new TimeParts(hour, minute, second, millisecond, kind, offset); } - protected virtual void GetDateFormatValues(DateParts parts, Calendar calendar, out int twoDigitYear, out string monthName, out string monthNameShort, out string monthNameGenitive, out string monthNameShortGenitive, out string dayName, out string dayNameShort) { + protected virtual void GetDateFormatValues(DateParts parts, Calendar calendar, out int twoDigitYear, out string monthName, out string monthNameShort, out string monthNameGenitive, out string monthNameShortGenitive, out string dayName, out string dayNameShort, out string eraName, out string eraNameShort) { var yearString = parts.Year.ToString("00", System.Globalization.CultureInfo.InvariantCulture); twoDigitYear = Int32.Parse(yearString.Substring(yearString.Length - 2)); monthName = parts.Month > 0 ? _dateTimeFormatProvider.MonthNames[parts.Month - 1] : null; @@ -298,7 +298,9 @@ namespace Orchard.Localization.Services { monthNameGenitive = parts.Month > 0 ? _dateTimeFormatProvider.MonthNamesGenitive[parts.Month - 1] : null; monthNameShortGenitive = parts.Month > 0 ? _dateTimeFormatProvider.MonthNamesShortGenitive[parts.Month - 1] : null; dayName = parts.Day > 0 ? _dateTimeFormatProvider.DayNames[(int)calendar.GetDayOfWeek(parts.ToDateTime(calendar))] : null; - dayNameShort = parts.Day > 0 ? _dateTimeFormatProvider.DayNamesShort[(int)calendar.GetDayOfWeek(parts.ToDateTime(calendar))] : null; + dayNameShort = parts.Day > 0 ? _dateTimeFormatProvider.DayNamesShort[(int)calendar.GetDayOfWeek(parts.ToDateTime(calendar))] : null; + eraName = parts.Day > 0 ? _dateTimeFormatProvider.GetEraName((int)calendar.GetEra(parts.ToDateTime(calendar))) : null; + eraNameShort = parts.Day > 0 ? _dateTimeFormatProvider.GetShortEraName((int)calendar.GetEra(parts.ToDateTime(calendar))) : null; } protected virtual void GetTimeFormatValues(TimeParts parts, out bool isPm, out int hour12, out string amPm, out string amPmShort, out string timeZone, out string offsetSign, out int offsetHours, out int offsetMinutes, out string fraction1Zero, out string fraction2Zero, out string fraction3Zero, out string fraction1Digit, out string fraction2Digit, out string fraction3Digit) { @@ -349,7 +351,9 @@ namespace Orchard.Localization.Services { {"yyyy", "(?[0-9]{4})"}, {"yyy", "(?[0-9]{3})"}, {"yy", "(?[0-9]{2})"}, - {"y", "(?[0-9]{1})"} + {"y", "(?[0-9]{1})"}, + {"gg", String.Format("(?{0})", String.Format("{0}|{1}", EscapeForRegex(_dateTimeFormatProvider.GetEraName(0)), EscapeForRegex(_dateTimeFormatProvider.GetEraName(1))))}, + {"g", String.Format("(?{0})", String.Format("{0}|{1}", EscapeForRegex(_dateTimeFormatProvider.GetEraName(0)), EscapeForRegex(_dateTimeFormatProvider.GetEraName(1))))} }; } @@ -404,40 +408,42 @@ namespace Orchard.Localization.Services { {"yyyy", "{0:0000}"}, {"yyy", "{0:000}"}, {"yy", "{1:00}"}, - {"y", "{1:0}"} + {"y", "{1:0}"}, + {"gg", "{10}"}, + {"g", "{10}"} }; } protected virtual Dictionary GetTimeFormatReplacements() { return new Dictionary() { - {"HH", "{10:00}"}, - {"H", "{10:#0}"}, - {"hh", "{11:00}"}, - {"h", "{11:#0}"}, - {"mm", "{12:00}"}, - {"m", "{12:#0}"}, - {"ss", "{13:00}"}, - {"s", "{13:#0}"}, - {"fffffff", "{16}0000"}, - {"ffffff", "{16}000"}, - {"fffff", "{16}00"}, - {"ffff", "{16}0"}, - {"fff", "{16}"}, - {"ff", "{15}"}, - {"f", "{14}"}, - {"FFFFFFF", "{19}"}, - {"FFFFFF", "{19}"}, - {"FFFFF", "{19}"}, - {"FFFF", "{19}"}, - {"FFF", "{19}"}, - {"FF", "{18}"}, - {"F", "{17}"}, - {"tt", "{20}"}, - {"t", "{21}"}, - {"K", "{22}"}, - {"zzz", "{23}{24:00}:{25:00}"}, - {"zz", "{23}{24:00}"}, - {"z", "{23}{24:#0}"} + {"HH", "{12:00}"}, + {"H", "{12:#0}"}, + {"hh", "{13:00}"}, + {"h", "{13:#0}"}, + {"mm", "{14:00}"}, + {"m", "{14:#0}"}, + {"ss", "{15:00}"}, + {"s", "{15:#0}"}, + {"fffffff", "{18}0000"}, + {"ffffff", "{18}000"}, + {"fffff", "{18}00"}, + {"ffff", "{18}0"}, + {"fff", "{18}"}, + {"ff", "{17}"}, + {"f", "{16}"}, + {"FFFFFFF", "{21}"}, + {"FFFFFF", "{21}"}, + {"FFFFF", "{21}"}, + {"FFFF", "{21}"}, + {"FFF", "{21}"}, + {"FF", "{20}"}, + {"F", "{19}"}, + {"tt", "{22}"}, + {"t", "{23}"}, + {"K", "{24}"}, + {"zzz", "{25}{26:00}:{27:00}"}, + {"zz", "{25}{26:00}"}, + {"z", "{25}{26:#0}"} }; } diff --git a/src/Orchard/Localization/Services/IDateTimeFormatProvider.cs b/src/Orchard/Localization/Services/IDateTimeFormatProvider.cs index c023cf974..dabcd1473 100644 --- a/src/Orchard/Localization/Services/IDateTimeFormatProvider.cs +++ b/src/Orchard/Localization/Services/IDateTimeFormatProvider.cs @@ -161,6 +161,21 @@ namespace Orchard.Localization.Services { /// string[] AmPmDesignators { get; - } + } + + /// + /// Returns a string containing the name of the specified era. + /// + string GetEraName(int era); + + /// + /// Returns a string containing the abbreviated name of the specified era, if an abbreviation exists. + /// + string GetShortEraName(int era); + + /// + /// Returns the integer representing the specified era. + /// + int GetEra(string eraName); } } From 61b8f82fd7f4f1b7ac948d3557e02b10d07731d7 Mon Sep 17 00:00:00 2001 From: jtkech Date: Thu, 7 May 2015 21:24:08 +0200 Subject: [PATCH 42/73] #5234 Duplicate lines in WorkflowManager --- .../Modules/Orchard.Workflows/Services/WorkflowManager.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Workflows/Services/WorkflowManager.cs b/src/Orchard.Web/Modules/Orchard.Workflows/Services/WorkflowManager.cs index eea418460..8795555f6 100644 --- a/src/Orchard.Web/Modules/Orchard.Workflows/Services/WorkflowManager.cs +++ b/src/Orchard.Web/Modules/Orchard.Workflows/Services/WorkflowManager.cs @@ -73,11 +73,6 @@ namespace Orchard.Workflows.Services { return; } - // if no activity record is matching the event, do nothing - if (!startedWorkflows.Any() && !awaitingActivities.Any()) { - return; - } - // resume halted workflows foreach (var awaitingActivityRecord in awaitingActivities) { var workflowContext = new WorkflowContext { @@ -292,4 +287,4 @@ namespace Orchard.Workflows.Services { return FormParametersHelper.FromJsonString("{}"); } } -} \ No newline at end of file +} From 085feeb11859fb4c7eca3d21a45527a4378e308b Mon Sep 17 00:00:00 2001 From: Kees Damen Date: Thu, 7 May 2015 23:36:21 +0200 Subject: [PATCH 43/73] added check for seeking-capability of inputStream in SaveStream before resetting the position --- .../Media/AzureBlobStorageProvider.cs | 17 ++++++++++------- .../Media/FileSystemStorageProvider.cs | 8 ++++---- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs b/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs index 1b162cb11..3a685be20 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs @@ -26,10 +26,10 @@ namespace Orchard.Azure.Services.FileSystems.Media { public bool TrySaveStream(string path, Stream inputStream) { try { - if (FileExists(path)) { - return false; - } - + if (FileExists(path)) { + return false; + } + SaveStream(path, inputStream); } catch { @@ -43,7 +43,9 @@ namespace Orchard.Azure.Services.FileSystems.Media { // Create the file. The CreateFile() method will map the still relative path. var file = CreateFile(path); - inputStream.Position = 0; // We need to read from the beginning of the stream, even if it isn't at it's beginning. + if (inputStream.CanSeek) { + inputStream.Position = 0; // We need to read from the beginning of the stream, even if it isn't at it's beginning. + } using (var outputStream = file.OpenWrite()) { var buffer = new byte[8192]; @@ -54,8 +56,9 @@ namespace Orchard.Azure.Services.FileSystems.Media { outputStream.Write(buffer, 0, length); } } - - inputStream.Position = 0; // Rolling back the stream so external readers will have it easier. + if (inputStream.CanSeek) { + inputStream.Position = 0; // Rolling back the stream so external readers will have it easier. + } } /// diff --git a/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs b/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs index dcf5a5a76..b7e790ff0 100644 --- a/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs +++ b/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs @@ -312,10 +312,10 @@ namespace Orchard.FileSystems.Media { /// True if success; False otherwise. public bool TrySaveStream(string path, Stream inputStream) { try { - if (FileExists(path)) { - return false; - } - + if (FileExists(path)) { + return false; + } + SaveStream(path, inputStream); } catch { From 9e66ee65601941aea7bd9fb591831806efd29056 Mon Sep 17 00:00:00 2001 From: Lombiq Date: Fri, 8 May 2015 16:30:26 +0200 Subject: [PATCH 44/73] Revert "Rolling back streams in storage providers, fixes #4860" This reverts commit f8e82be4b90bf31a9d591229e54b1f101daa832c. There are Stream implementation that don't support seeking so we can't do Position resetting just every time. --- .../FileSystems/Media/AzureBlobStorageProvider.cs | 4 ---- .../FileSystems/Media/FileSystemStorageProvider.cs | 12 ++++-------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs b/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs index 1b162cb11..2e38b1cfa 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs @@ -43,8 +43,6 @@ namespace Orchard.Azure.Services.FileSystems.Media { // Create the file. The CreateFile() method will map the still relative path. var file = CreateFile(path); - inputStream.Position = 0; // We need to read from the beginning of the stream, even if it isn't at it's beginning. - using (var outputStream = file.OpenWrite()) { var buffer = new byte[8192]; while (true) { @@ -54,8 +52,6 @@ namespace Orchard.Azure.Services.FileSystems.Media { outputStream.Write(buffer, 0, length); } } - - inputStream.Position = 0; // Rolling back the stream so external readers will have it easier. } /// diff --git a/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs b/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs index dcf5a5a76..e4ad40152 100644 --- a/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs +++ b/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs @@ -312,10 +312,10 @@ namespace Orchard.FileSystems.Media { /// True if success; False otherwise. public bool TrySaveStream(string path, Stream inputStream) { try { - if (FileExists(path)) { - return false; - } - + if (FileExists(path)) { + return false; + } + SaveStream(path, inputStream); } catch { @@ -336,8 +336,6 @@ namespace Orchard.FileSystems.Media { // The CreateFile method will map the still relative path var file = CreateFile(path); - inputStream.Position = 0; // We need to read from the beginning of the stream, even if it isn't at it's beginning. - using (var outputStream = file.OpenWrite()) { var buffer = new byte[8192]; for (; ; ) { @@ -348,8 +346,6 @@ namespace Orchard.FileSystems.Media { outputStream.Write(buffer, 0, length); } } - - inputStream.Position = 0; // Rolling back the stream so external readers will have it easier. } /// From b4c578a2c5ddef83b944eef1d4e3145beb3823ee Mon Sep 17 00:00:00 2001 From: Kees Damen Date: Fri, 8 May 2015 19:38:46 +0200 Subject: [PATCH 45/73] Revert "added check for seeking-capability of inputStream in SaveStream before resetting the position" This reverts commit 085feeb11859fb4c7eca3d21a45527a4378e308b. --- .../Media/AzureBlobStorageProvider.cs | 17 +++++++---------- .../Media/FileSystemStorageProvider.cs | 8 ++++---- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs b/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs index 3a685be20..1b162cb11 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs @@ -26,10 +26,10 @@ namespace Orchard.Azure.Services.FileSystems.Media { public bool TrySaveStream(string path, Stream inputStream) { try { - if (FileExists(path)) { - return false; - } - + if (FileExists(path)) { + return false; + } + SaveStream(path, inputStream); } catch { @@ -43,9 +43,7 @@ namespace Orchard.Azure.Services.FileSystems.Media { // Create the file. The CreateFile() method will map the still relative path. var file = CreateFile(path); - if (inputStream.CanSeek) { - inputStream.Position = 0; // We need to read from the beginning of the stream, even if it isn't at it's beginning. - } + inputStream.Position = 0; // We need to read from the beginning of the stream, even if it isn't at it's beginning. using (var outputStream = file.OpenWrite()) { var buffer = new byte[8192]; @@ -56,9 +54,8 @@ namespace Orchard.Azure.Services.FileSystems.Media { outputStream.Write(buffer, 0, length); } } - if (inputStream.CanSeek) { - inputStream.Position = 0; // Rolling back the stream so external readers will have it easier. - } + + inputStream.Position = 0; // Rolling back the stream so external readers will have it easier. } /// diff --git a/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs b/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs index b7e790ff0..dcf5a5a76 100644 --- a/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs +++ b/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs @@ -312,10 +312,10 @@ namespace Orchard.FileSystems.Media { /// True if success; False otherwise. public bool TrySaveStream(string path, Stream inputStream) { try { - if (FileExists(path)) { - return false; - } - + if (FileExists(path)) { + return false; + } + SaveStream(path, inputStream); } catch { From c73d6c0a9129b9f39c03c6d0656c153da8803556 Mon Sep 17 00:00:00 2001 From: Lombiq Date: Fri, 8 May 2015 21:14:06 +0200 Subject: [PATCH 46/73] Removing empty RouteExtension, fixes #2509 --- src/Orchard/Mvc/Routes/RouteExtensions.cs | 5 ----- src/Orchard/Orchard.Framework.csproj | 1 - 2 files changed, 6 deletions(-) delete mode 100644 src/Orchard/Mvc/Routes/RouteExtensions.cs diff --git a/src/Orchard/Mvc/Routes/RouteExtensions.cs b/src/Orchard/Mvc/Routes/RouteExtensions.cs deleted file mode 100644 index a55bef517..000000000 --- a/src/Orchard/Mvc/Routes/RouteExtensions.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace Orchard.Mvc.Routes { - public static class RouteExtensions { - - } -} diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index ce395e66c..7a3ce7d31 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -933,7 +933,6 @@ - From 91e040e684a874bd410a2259f45070b0b7f55945 Mon Sep 17 00:00:00 2001 From: Lombiq Date: Mon, 11 May 2015 16:52:54 +0200 Subject: [PATCH 47/73] Fixing that the technical names of widgets couldn't contain hyphens, see #4981 --- .../Drivers/WidgetPartDriver.cs | 2 +- .../Utility/Extensions/StringExtensions.cs | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs index 9a3fba25c..4016c9f17 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs @@ -53,7 +53,7 @@ namespace Orchard.Widgets.Drivers { // if there is a name, ensure it's unique if(!string.IsNullOrWhiteSpace(widgetPart.Name)) { - widgetPart.Name = widgetPart.Name.ToSafeName(); + widgetPart.Name = widgetPart.Name.ToHtmlName(); var widgets = _contentManager.Query().Where(x => x.Name == widgetPart.Name && x.Id != widgetPart.Id).Count(); if(widgets > 0) { diff --git a/src/Orchard/Utility/Extensions/StringExtensions.cs b/src/Orchard/Utility/Extensions/StringExtensions.cs index 65a6c73e9..d1290b794 100644 --- a/src/Orchard/Utility/Extensions/StringExtensions.cs +++ b/src/Orchard/Utility/Extensions/StringExtensions.cs @@ -191,6 +191,34 @@ namespace Orchard.Utility.Extensions { return name; } + /// + /// Generates a valid Html name. + /// + /// + /// Uses a white list set of chars. + /// + public static string ToHtmlName(this string name) { + if (String.IsNullOrWhiteSpace(name)) + return String.Empty; + + name = RemoveDiacritics(name); + name = name.Strip(c => + c != '-' + && c != '_' + && !c.IsLetter() + && !Char.IsDigit(c) + ); + + name = name.Trim(); + + // don't allow non A-Z chars as first letter, as they are not allowed in prefixes + while (name.Length > 0 && !IsLetter(name[0])) { + name = name.Substring(1); + } + + return name; + } + /// /// Whether the char is a letter between A and Z or not /// From 40243f2224452033a4826d22f56fd31da2368c66 Mon Sep 17 00:00:00 2001 From: Lombiq Date: Mon, 11 May 2015 23:17:58 +0200 Subject: [PATCH 48/73] Indexing task creation now happens gradually in a background task, preventing timeout/out of memory when editing a content type with many items. Fixes #4729. --- .../Modules/Orchard.Indexing/Migrations.cs | 29 +++++++++- .../Models/IndexTaskBatchRecord.cs | 7 +++ .../Orchard.Indexing/Orchard.Indexing.csproj | 4 ++ .../CreateUpdateIndexTaskBackgroundTask.cs | 25 +++++++++ .../IIndexTaskBatchManagementService.cs | 21 ++++++++ .../IndexTaskBatchManagementService.cs | 53 +++++++++++++++++++ .../Orchard.Indexing/Settings/EditorEvents.cs | 48 +++++------------ 7 files changed, 150 insertions(+), 37 deletions(-) create mode 100644 src/Orchard.Web/Modules/Orchard.Indexing/Models/IndexTaskBatchRecord.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Indexing/Services/CreateUpdateIndexTaskBackgroundTask.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Indexing/Services/IIndexTaskBatchManagementService.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexTaskBatchManagementService.cs diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Migrations.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Migrations.cs index 5905ff0d2..1d57200ba 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Migrations.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Migrations.cs @@ -20,7 +20,18 @@ namespace Orchard.Indexing { .Column("ContentItemRecord_id") ); - return 2; + SchemaBuilder.CreateTable("IndexTaskBatchRecord", + table => table + .Column("Id", column => column.PrimaryKey().Identity()) + .Column("BatchStartIndex") + .Column("ContentType") + ) + .AlterTable("IndexTaskBatchRecord", + table => + table.CreateIndex("IDX_ContentType", "ContentType") + ); + + return 3; } public int UpdateFrom1() { @@ -35,5 +46,21 @@ namespace Orchard.Indexing { return 2; } + + public int UpdateFrom2() { + + SchemaBuilder.CreateTable("IndexTaskBatchRecord", + table => table + .Column("Id", column => column.PrimaryKey().Identity()) + .Column("BatchStartIndex") + .Column("ContentType") + ) + .AlterTable("IndexTaskBatchRecord", + table => + table.CreateIndex("IDX_ContentType", "ContentType") + ); + + return 3; + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Models/IndexTaskBatchRecord.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Models/IndexTaskBatchRecord.cs new file mode 100644 index 000000000..2ba820b46 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Models/IndexTaskBatchRecord.cs @@ -0,0 +1,7 @@ +namespace Orchard.Indexing.Models { + public class IndexTaskBatchRecord { + public virtual int Id { get; set; } + public virtual int BatchStartIndex { get; set; } + public virtual string ContentType { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj b/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj index eae542b6a..c783ef9c5 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj @@ -78,6 +78,9 @@ Code + + + @@ -91,6 +94,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Services/CreateUpdateIndexTaskBackgroundTask.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Services/CreateUpdateIndexTaskBackgroundTask.cs new file mode 100644 index 000000000..1418ad37f --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Services/CreateUpdateIndexTaskBackgroundTask.cs @@ -0,0 +1,25 @@ +using System.Linq; +using Orchard.Tasks; +using Orchard.Tasks.Indexing; + +namespace Orchard.Indexing.Services { + public class CreateUpdateIndexTaskBackgroundTask : IBackgroundTask { + private readonly IIndexTaskBatchManagementService _indexTaskBatchManagementService; + private readonly IIndexingTaskManager _indexingTaskManager; + + public CreateUpdateIndexTaskBackgroundTask(IIndexTaskBatchManagementService indexTaskBatchManagementService, IIndexingTaskManager indexingTaskManager) { + _indexTaskBatchManagementService = indexTaskBatchManagementService; + _indexingTaskManager = indexingTaskManager; + } + + public void Sweep() { + var contentItemsLists = _indexTaskBatchManagementService.GetNextBatchOfContentItemsToIndex(); + + foreach (var contentItemsList in contentItemsLists) { + foreach (var contentItem in contentItemsList) { + _indexingTaskManager.CreateUpdateIndexTask(contentItem); + } + } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Services/IIndexTaskBatchManagementService.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Services/IIndexTaskBatchManagementService.cs new file mode 100644 index 000000000..233b52262 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Services/IIndexTaskBatchManagementService.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using Orchard.ContentManagement; + +namespace Orchard.Indexing.Services { + /// + /// Manages the batches for indexing tasks. + /// + public interface IIndexTaskBatchManagementService : IDependency { + + /// + /// Registers a content type for the . + /// + /// The content type. + void RegisterContentType(string contentType); + + /// + /// Returns a list of a list of the registered content items. + /// + IEnumerable> GetNextBatchOfContentItemsToIndex(); + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexTaskBatchManagementService.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexTaskBatchManagementService.cs new file mode 100644 index 000000000..963499012 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexTaskBatchManagementService.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; +using System.Linq; +using Orchard.ContentManagement; +using Orchard.Data; +using Orchard.Indexing.Models; + +namespace Orchard.Indexing.Services { + public class IndexTaskBatchManagementService : IIndexTaskBatchManagementService { + private readonly IRepository _indexTaskBatchRecordRepository; + private readonly IContentManager _contentManager; + + private const int BatchSize = 50; + + public IndexTaskBatchManagementService(IRepository indexTaskBatchRecordRepository, IContentManager contentManager) { + _indexTaskBatchRecordRepository = indexTaskBatchRecordRepository; + _contentManager = contentManager; + } + + public void RegisterContentType(string contentType) { + var registeredContentType = _indexTaskBatchRecordRepository.Table.Where(i => i.ContentType == contentType).FirstOrDefault(); + + if (registeredContentType == null) { + _indexTaskBatchRecordRepository.Create(new IndexTaskBatchRecord { ContentType = contentType, BatchStartIndex = 0 }); + } + else { + registeredContentType.BatchStartIndex = 0; + } + + } + + public IEnumerable> GetNextBatchOfContentItemsToIndex() { + var indexTaskBatchRecords = _indexTaskBatchRecordRepository.Table; + if (indexTaskBatchRecords == null) return null; + + var contentItemsList = new List>(); + + foreach (var indexTaskBatchRecord in indexTaskBatchRecords) { + var contentItems = _contentManager.Query(indexTaskBatchRecord.ContentType).Slice(indexTaskBatchRecord.BatchStartIndex, BatchSize).ToList(); + + if (contentItems.Any()) contentItemsList.Add(contentItems); + + if (contentItems.Count == 0 || contentItems.Count < BatchSize) { + _indexTaskBatchRecordRepository.Delete(_indexTaskBatchRecordRepository.Table.FirstOrDefault(i => i.ContentType == indexTaskBatchRecord.ContentType)); + } + else { + indexTaskBatchRecord.BatchStartIndex += BatchSize; + } + } + + return contentItemsList; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs index d4de846b8..37a6d3426 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs @@ -1,27 +1,23 @@ -using System.Collections.Generic; -using System.Linq; +using System; +using System.Collections.Generic; using Orchard.ContentManagement; using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData.Builders; using Orchard.ContentManagement.MetaData.Models; using Orchard.ContentManagement.ViewModels; -using Orchard.Tasks.Indexing; +using Orchard.Indexing.Services; namespace Orchard.Indexing.Settings { public class EditorEvents : ContentDefinitionEditorEventsBase { - private readonly IIndexingTaskManager _indexingTaskManager; - private readonly IContentManager _contentManager; - - private const int PageSize = 50; - - public EditorEvents(IIndexingTaskManager indexingTaskManager, IContentManager contentManager){ - _indexingTaskManager = indexingTaskManager; - _contentManager = contentManager; - } + private readonly IIndexTaskBatchManagementService _indexTaskBatchManagementService; private string _contentTypeName; private bool _tasksCreated; + public EditorEvents(IIndexTaskBatchManagementService indexTaskBatchManagementService) { + _indexTaskBatchManagementService = indexTaskBatchManagementService; + } + public override IEnumerable TypeEditor(ContentTypeDefinition definition) { var model = definition.Settings.GetModel(); _contentTypeName = definition.Name; @@ -41,12 +37,12 @@ namespace Orchard.Indexing.Settings { // if a an index is added, all existing content items need to be re-indexed CreateIndexingTasks(); } - + yield return DefinitionTemplate(model); } private string Clean(string value) { - if (string.IsNullOrEmpty(value)) + if (String.IsNullOrEmpty(value)) return value; return value.Trim(',', ' '); @@ -57,7 +53,8 @@ namespace Orchard.Indexing.Settings { /// private void CreateIndexingTasks() { if (!_tasksCreated) { - CreateTasksForType(_contentTypeName); + // Creating tasks in batches is needed because editing content type settings for a type with many items causes OutOfMemoryException, see issue: https://github.com/OrchardCMS/Orchard/issues/4729 + _indexTaskBatchManagementService.RegisterContentType(_contentTypeName); _tasksCreated = true; } } @@ -83,26 +80,5 @@ namespace Orchard.Indexing.Settings { yield return DefinitionTemplate(model); } - - private void CreateTasksForType(string type) { - var index = 0; - bool contentItemProcessed; - - // todo: load ids only, or create a queued job - // we create a task even for draft items, and the executor will filter based on the settings - - do { - contentItemProcessed = false; - var contentItemsToIndex = _contentManager.Query(VersionOptions.Latest, new [] { type }).Slice(index, PageSize); - - foreach (var contentItem in contentItemsToIndex) { - contentItemProcessed = true; - _indexingTaskManager.CreateUpdateIndexTask(contentItem); - } - - index += PageSize; - - } while (contentItemProcessed); - } } } \ No newline at end of file From f932cc394f6ee0a833b77ef27dfd37b6d749c256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Leh=C3=B3czky?= Date: Thu, 14 May 2015 00:36:31 +0200 Subject: [PATCH 49/73] Adding Select all checkbox to all suitable admin lists, fixes #5026 --- src/Orchard.Web/Core/Contents/Views/Admin/List.cshtml | 2 ++ .../Modules/Orchard.Blogs/Views/BlogAdmin/List.cshtml | 1 + .../Orchard.Blogs/Views/Parts.Blogs.BlogPost.ListAdmin.cshtml | 4 +++- .../Modules/Orchard.ImportExport/Views/Admin/Export.cshtml | 1 + .../Modules/Orchard.Projections/Views/Admin/Index.cshtml | 2 +- .../Modules/Orchard.Taxonomies/Views/TermAdmin/Index.cshtml | 2 +- .../Modules/Orchard.Templates/Views/Admin/List.cshtml | 1 + src/Orchard.Web/Themes/TheAdmin/Scripts/admin.js | 2 +- 8 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Orchard.Web/Core/Contents/Views/Admin/List.cshtml b/src/Orchard.Web/Core/Contents/Views/Admin/List.cshtml index e091e129f..a678329b5 100644 --- a/src/Orchard.Web/Core/Contents/Views/Admin/List.cshtml +++ b/src/Orchard.Web/Core/Contents/Views/Admin/List.cshtml @@ -16,8 +16,10 @@
@Html.ActionLink(createLinkText.Text, "Create", new { Area = "Contents", Id = (string)Model.Options.SelectedFilter }, new { @class = "button primaryAction" })
+ @using (Html.BeginFormAntiForgeryPost()) {
+ @T(" | ") @T("Select all")@T(" | ") @T("Select all")@T(" | ") @T("Select all")
    @{var contentTypeIndex = 0;} @foreach (var contentTypeEntry in Model.ContentTypes) { diff --git a/src/Orchard.Web/Modules/Orchard.Projections/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.Projections/Views/Admin/Index.cshtml index 3b89642d9..db45f22fe 100644 --- a/src/Orchard.Web/Modules/Orchard.Projections/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Projections/Views/Admin/Index.cshtml @@ -18,8 +18,8 @@ @using (Html.BeginFormAntiForgeryPost()) { @Html.ValidationSummary()
    @Html.ActionLink(T("Add a new Query").ToString(), "Create", new { Area = "Contents", id = "Query", returnurl = HttpContext.Current.Request.RawUrl }, new { @class = "button primaryAction" })
    -
    + @T(" | ") @T("Name") diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Views/Admin/List.cshtml b/src/Orchard.Web/Modules/Orchard.Templates/Views/Admin/List.cshtml index 682f94bc2..d37398f51 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Views/Admin/List.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Templates/Views/Admin/List.cshtml @@ -16,6 +16,7 @@ @using (Html.BeginFormAntiForgeryPost()) {
    + @T(" | ") + @T("One term per line, followed by a semi-colon and the slug") @T("Hierarchies are defined using tabs (handled in this editor zone)") @@ -21,47 +21,47 @@ } -@using(Script.Foot()){ - + //]]> + } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/Admin/Index.cshtml index d996c26fb..6eaebdffa 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/Admin/Index.cshtml @@ -7,59 +7,59 @@ } @using (Html.BeginFormAntiForgeryPost()) { - @Html.ValidationSummary() -
    - - - -
    -
    @Html.ActionLink(T("Add a taxonomy").Text, "Create", new { Area = "Contents", Id = "Taxonomy", ReturnUrl = Request.RawUrl }, new { @class = "button primaryAction" })
    -
    - - - - - - - - - - - - - - @foreach (var taxonomyEntry in Model.Taxonomies) { - ti = taxonomyIndex; - - - - - - taxonomyIndex++; - } -
    @T("Name")
    - - @if (!taxonomyEntry.IsInternal || Authorizer.Authorize(Orchard.Security.StandardPermissions.SiteOwner)) { - - } - - @if (!taxonomyEntry.IsInternal || Authorizer.Authorize(Orchard.Security.StandardPermissions.SiteOwner)) { - @Html.ActionLink(taxonomyEntry.Name, "Index", "TermAdmin", new { taxonomyId = taxonomyEntry.Id }, new object { }) - } - else { - @Html.ItemDisplayText(taxonomyEntry.ContentItem) - } - - @if (!taxonomyEntry.IsInternal || Authorizer.Authorize(Orchard.Security.StandardPermissions.SiteOwner)) { - @Html.ItemEditLink(T("Edit").Text, taxonomyEntry.ContentItem) | - @Html.ActionLink(T("Terms").Text, "Index", "TermAdmin", new { taxonomyId = taxonomyEntry.Id }, new object { }) | - @Html.ActionLink(T("Delete").Text, "Delete", new { id = taxonomyEntry.Id }, new object { }) | - @Html.ActionLink(T("Import").Text, "Import", new { id = taxonomyEntry.Id }, new object { }) - } -
    + @Html.ValidationSummary() +
    + + + +
    +
    @Html.ActionLink(T("Add a taxonomy").Text, "Create", new { Area = "Contents", Id = "Taxonomy", ReturnUrl = Request.RawUrl }, new { @class = "button primaryAction" })
    +
    + + + + + + + + + + + + + + @foreach (var taxonomyEntry in Model.Taxonomies) { + ti = taxonomyIndex; + + + + + + taxonomyIndex++; + } +
    @T("Name")
    + + @if (!taxonomyEntry.IsInternal || Authorizer.Authorize(Orchard.Security.StandardPermissions.SiteOwner)) { + + } + + @if (!taxonomyEntry.IsInternal || Authorizer.Authorize(Orchard.Security.StandardPermissions.SiteOwner)) { + @Html.ActionLink(taxonomyEntry.Name, "Index", "TermAdmin", new { taxonomyId = taxonomyEntry.Id }, new object { }) + } + else { + @Html.ItemDisplayText(taxonomyEntry.ContentItem) + } + + @if (!taxonomyEntry.IsInternal || Authorizer.Authorize(Orchard.Security.StandardPermissions.SiteOwner)) { + @Html.ItemEditLink(T("Edit").Text, taxonomyEntry.ContentItem) | + @Html.ActionLink(T("Terms").Text, "Index", "TermAdmin", new { taxonomyId = taxonomyEntry.Id }, new object { }) | + @Html.ActionLink(T("Delete").Text, "Delete", new { id = taxonomyEntry.Id }, new object { }) | + @Html.ActionLink(T("Import").Text, "Import", new { id = taxonomyEntry.Id }, new object { }) + } +
    @Display(Model.Pager) -
    +
    } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/DefinitionTemplates/TaxonomyFieldSettings.cshtml b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/DefinitionTemplates/TaxonomyFieldSettings.cshtml index 33e8d0c8a..bb79ef4f6 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/DefinitionTemplates/TaxonomyFieldSettings.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/DefinitionTemplates/TaxonomyFieldSettings.cshtml @@ -3,10 +3,10 @@ Script.Include("admin-taxonomy-field-settings.js").AtFoot(); }
    - + @@ -14,10 +14,10 @@
    - +
    - @Html.CheckBoxFor(m => m.LeavesOnly) + @Html.CheckBoxFor(m => m.LeavesOnly)
    @@ -32,7 +32,7 @@
    - + @Html.CheckBoxFor(m => m.Autocomplete)
    @Html.CheckBoxFor(m => m.AllowCustomTerms) @@ -41,7 +41,7 @@
    - @Html.TextAreaFor(m => m.Hint, new { @class = "text medium", rows = "5" } ) + @Html.TextAreaFor(m => m.Hint, new { @class = "text medium", rows = "5" }) @T("The help text is written under the field when authors are editing the content item.") @Html.ValidationMessageFor(m => m.Hint)
    \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.Autocomplete.cshtml b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.Autocomplete.cshtml index 58c11b444..71caa17ad 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.Autocomplete.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.Autocomplete.cshtml @@ -26,52 +26,52 @@ } } @{ - var allTerms = Newtonsoft.Json.JsonConvert.SerializeObject(Model.Terms.Select(x => new { label = x.Name, value = x.Id, levels = x.GetLevels(), disabled = IsTermDisabled(x)})); + var allTerms = Newtonsoft.Json.JsonConvert.SerializeObject(Model.Terms.Select(x => new { label = x.Name, value = x.Id, levels = x.GetLevels(), disabled = IsTermDisabled(x) })); var selectedTerms = Newtonsoft.Json.JsonConvert.SerializeObject(Model.Terms.Where(x => x.IsChecked).Select(x => new { label = x.Name, value = x.Id, levels = 0, disabled = true })); }
    - class="required" }>@Model.DisplayName.CamelFriendly() + class="required" }>@Model.DisplayName.CamelFriendly() @if (Model.Settings.Autocomplete) { -
    -
      - @if (Model.Settings.SingleChoice) { -
      @T("Enter a single term. Hit tab or enter to apply the term.") @if (!Model.Settings.AllowCustomTerms) { @T("This taxonomy does not allow you to create new terms.") }
      - } - else { -
      @T("Enter multiple terms. Hit tab, enter or , to add multiple terms.") @if (!Model.Settings.AllowCustomTerms) { @T("This taxonomy does not allow you to create new terms.") }
      - } -
      +
      +
        + @if (Model.Settings.SingleChoice) { +
        @T("Enter a single term. Hit tab or enter to apply the term.") @if (!Model.Settings.AllowCustomTerms) { @T("This taxonomy does not allow you to create new terms.") }
        + } + else { +
        @T("Enter multiple terms. Hit tab, enter or , to add multiple terms.") @if (!Model.Settings.AllowCustomTerms) { @T("This taxonomy does not allow you to create new terms.") }
        + } +
        } @if (!String.IsNullOrWhiteSpace(Model.Settings.Hint)) { - @Model.Settings.Hint + @Model.Settings.Hint }
          - @foreach (var entry in Model.Terms) { - var ti = termIndex; -
        • - @{ - var disabled = IsTermDisabled(entry); - if (Model.Settings.SingleChoice) { - disabled="disabled" } type="radio" value="@Model.Terms[ti].Id" @if (entry.Id == Model.SingleTermId){ checked="checked" } name="@Html.FieldNameFor(m => m.SingleTermId)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name" data-term-identity="@entry.Name.ToLower()" /> + @foreach (var entry in Model.Terms) { + var ti = termIndex; +
        • + @{ + var disabled = IsTermDisabled(entry); + if (Model.Settings.SingleChoice) { + disabled="disabled" } type="radio" value="@Model.Terms[ti].Id" @if (entry.Id == Model.SingleTermId) { checked="checked" } name="@Html.FieldNameFor(m => m.SingleTermId)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name" data-term-identity="@entry.Name.ToLower()" /> + } + else { + disabled="disabled" } type="checkbox" value="true" @if (entry.IsChecked) { checked="checked" } name="@Html.FieldNameFor(m => m.Terms[ti].IsChecked)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name" data-term-identity="@entry.Name.ToLower()" /> + } } - else { - disabled="disabled" } type="checkbox" value="true" @if (entry.IsChecked) { checked="checked" } name="@Html.FieldNameFor(m => m.Terms[ti].IsChecked)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name" data-term-identity="@entry.Name.ToLower()" /> - } - } - - @Html.HiddenFor(m => m.Terms[ti].Id) -
        • - termIndex++; - } + + @Html.HiddenFor(m => m.Terms[ti].Id) + + termIndex++; + }
        - + @if (!Model.Terms.Any()) { -
        - @T("There are no terms defined for {0} yet.", Model.DisplayName.CamelFriendly()) - @T("Create some terms") -
        +
        + @T("There are no terms defined for {0} yet.", Model.DisplayName.CamelFriendly()) + @T("Create some terms") +
        } @Html.HiddenFor(m => m.TaxonomyId)
        diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.cshtml b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.cshtml index a5e52893a..48461ed28 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.cshtml @@ -5,7 +5,7 @@ @{ Style.Include("admin-taxonomy.css"); - Script.Require("jQuery"); + Script.Require("jQuery"); Script.Include("~/Themes/TheAdmin/scripts/admin.js").AtFoot(); Script.Include("admin-taxonomy-expando.js").AtFoot(); @@ -14,40 +14,39 @@ }
        - class="required" }>@Model.DisplayName.CamelFriendly() - + class="required" }>@Model.DisplayName.CamelFriendly() +
        - @if (!String.IsNullOrWhiteSpace(Model.Settings.Hint)) - { + @if (!String.IsNullOrWhiteSpace(Model.Settings.Hint)) { @Model.Settings.Hint } - +
          @foreach (var entry in Model.Terms) { var ti = termIndex;
        • - @* Tabs for levels *@ @for (var i = 1; i <= entry.GetLevels(); i++){   } + @* Tabs for levels *@ @for (var i = 1; i <= entry.GetLevels(); i++) {   } @{ - var disabled = !entry.Selectable || (Model.Settings.LeavesOnly && Model.Terms.Any(t => t.Path.Contains(entry.Path + entry.Id))); - if (Model.Settings.SingleChoice) { - disabled="disabled" } type="radio" value="@Model.Terms[ti].Id" @if (entry.Id == Model.SingleTermId) { checked="checked" } name="@Html.FieldNameFor(m => m.SingleTermId)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name.ToLower()"/> - } - else { - disabled="disabled" } type="checkbox" value="true" @if (entry.IsChecked){ checked="checked" } name="@Html.FieldNameFor(m => m.Terms[ti].IsChecked)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name.ToLower()"/> - } + var disabled = !entry.Selectable || (Model.Settings.LeavesOnly && Model.Terms.Any(t => t.Path.Contains(entry.Path + entry.Id))); + if (Model.Settings.SingleChoice) { + disabled="disabled" } type="radio" value="@Model.Terms[ti].Id" @if (entry.Id == Model.SingleTermId) { checked="checked" } name="@Html.FieldNameFor(m => m.SingleTermId)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name.ToLower()" /> + } + else { + disabled="disabled" } type="checkbox" value="true" @if (entry.IsChecked) { checked="checked" } name="@Html.FieldNameFor(m => m.Terms[ti].IsChecked)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name.ToLower()" /> + } } @Html.HiddenFor(m => m.Terms[ti].Id)
        • - termIndex++; + termIndex++; }
        - + @if (!Model.Terms.Any()) {
        @T("There are no terms defined for {0} yet.", Model.DisplayName.CamelFriendly()) @T("Create some terms") -
        +
        }
        @Html.HiddenFor(m => m.TaxonomyId) diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Parts/Navigation.Taxonomy.Edit.cshtml b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Parts/Navigation.Taxonomy.Edit.cshtml index 790f5be56..01d639263 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Parts/Navigation.Taxonomy.Edit.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Parts/Navigation.Taxonomy.Edit.cshtml @@ -2,66 +2,66 @@ @using Orchard.Taxonomies.ViewModels; @{ - Script.Require("jQuery"); + Script.Require("jQuery"); }
        - @Html.LabelFor(m => m.SelectedTaxonomyId, T("Taxonomy")) - @Html.DropDownListFor(m => m.SelectedTaxonomyId, Model.AvailableTaxonomies) + @Html.LabelFor(m => m.SelectedTaxonomyId, T("Taxonomy")) + @Html.DropDownListFor(m => m.SelectedTaxonomyId, Model.AvailableTaxonomies) @T("Select the taxonomy whose terms will be rendered in the menu.")
        - @Html.LabelFor(m => m.SelectedTermId, T("Root Term")) - + @Html.SelectOption(-1, false, T("- Parent Taxonomy -").ToString()) + @{Html.RenderAction("RenderTermSelect", "TermAdmin", new { area = "Orchard.Taxonomies", taxonomyId = Model.SelectedTaxonomyId, selectedTermId = Model.SelectedTermId });} - @T("Select the root term to display") + @T("Select the root term to display")
        - @Html.CheckBoxFor(m => m.DisplayTopMenuItem) - - @T("When checked, the selected term to display will be rendered as a root element in the menu.") + @Html.CheckBoxFor(m => m.DisplayTopMenuItem) + + @T("When checked, the selected term to display will be rendered as a root element in the menu.")
        - @Html.TextBoxFor(m => m.LevelsToDisplay, new { @class = "text small" } ) + @Html.TextBoxFor(m => m.LevelsToDisplay, new { @class = "text small" }) @Html.ValidationMessage("LevelsToDisplay", "*") @T("The number of levels to display in the hierarchy. 0 to display all levels.")
        - @Html.CheckBoxFor(m => m.HideEmptyTerms) - - @T("When checked, any term which has no content item associated to it won't be rendered.") + @Html.CheckBoxFor(m => m.HideEmptyTerms) + + @T("When checked, any term which has no content item associated to it won't be rendered.")
        - @Html.CheckBoxFor(m => m.DisplayContentCount) - - @T("When checked, the number of content items is rendered following the term name.") + @Html.CheckBoxFor(m => m.DisplayContentCount) + + @T("When checked, the number of content items is rendered following the term name.")
        @using (Script.Foot()) { - + $.get( + "@Url.Action("RenderTermSelect", "TermAdmin", new { area = "Orchard.Taxonomies" })", { taxonomyId: id }, function (data) { + $('#@Html.FieldIdFor(m => m.SelectedTermId) option[value != -1]').remove(); + $('#@Html.FieldIdFor(m => m.SelectedTermId)').append(data); + }); + }); + }) + //]]> + } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/Fields/TaxonomyField.cshtml b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/Fields/TaxonomyField.cshtml index 00824b29a..c6f81466a 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/Fields/TaxonomyField.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/Fields/TaxonomyField.cshtml @@ -4,8 +4,8 @@ string name = @Model.ContentField.DisplayName; } @if (Model.Terms.Count > 0) { -

        - @name.CamelFriendly(): - @(new HtmlString( string.Join(", ", terms.Select(t => Html.ItemDisplayLink(t.Name, t.ContentItem ).ToString()).ToArray()) )) -

        +

        + @name.CamelFriendly(): + @(new HtmlString(string.Join(", ", terms.Select(t => Html.ItemDisplayLink(t.Name, t.ContentItem).ToString()).ToArray()))) +

        } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/Taxonomy.cshtml b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/Taxonomy.cshtml index c62354436..5090f9868 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/Taxonomy.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/Taxonomy.cshtml @@ -11,7 +11,7 @@ if (items.Any()) { items[0].Classes.Add("first"); items[items.Count - 1].Classes.Add("last"); - } + } }
        @tag.StartElement diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TaxonomyItem.cshtml b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TaxonomyItem.cshtml index 948924868..3be467fcc 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TaxonomyItem.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TaxonomyItem.cshtml @@ -1,4 +1,4 @@ -@* +@* This shape is displayed for a TermPart when in a Taxonomy details page Its children are the element shapes in the list. Alternates: @@ -16,21 +16,21 @@ var tag = Tag(Model, "li"); @tag.StartElement - @* - - morphing the shape to keep Model untouched and - - provide a simple way to customize the shape - *@ - - Model.Metadata.Alternates.Clear(); - Model.Metadata.Type = "TaxonomyItemLink"; - @Display(Model) + @* + - morphing the shape to keep Model untouched and + - provide a simple way to customize the shape + *@ - @* render child elements *@ - - if (items.Any()) { -
          - @DisplayChildren(Model) -
        - } + Model.Metadata.Alternates.Clear(); + Model.Metadata.Type = "TaxonomyItemLink"; + @Display(Model) + + @* render child elements *@ + + if (items.Any()) { +
          + @DisplayChildren(Model) +
        + } @tag.EndElement } diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/Merge.cshtml b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/Merge.cshtml index c4791f66f..645ba6ef9 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/Merge.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/Merge.cshtml @@ -11,7 +11,7 @@ diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/MoveTerm.cshtml b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/MoveTerm.cshtml index e1aefa419..d2c876e59 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/MoveTerm.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/MoveTerm.cshtml @@ -11,9 +11,9 @@ + @T("By selecting a parent term you can create hierarchies")
        diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/RenderTermSelect.cshtml b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/RenderTermSelect.cshtml index 092edb39d..ca66d82d6 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/RenderTermSelect.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/RenderTermSelect.cshtml @@ -3,5 +3,5 @@ @using Orchard.Taxonomies.Helpers; @foreach (var term in Model.Terms) { - + } diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/SelectTerm.cshtml b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/SelectTerm.cshtml index 644613d5d..30a8a8c9c 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/SelectTerm.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/TermAdmin/SelectTerm.cshtml @@ -9,9 +9,9 @@ + @T("By selecting a parent term you can create hierarchies")
        From 15ccba2b8122e002d6f1fac8fd83d1aad6de7ecc Mon Sep 17 00:00:00 2001 From: Lombiq Date: Wed, 20 May 2015 00:27:57 +0200 Subject: [PATCH 62/73] Fixing that Orchard.Email Workflows classes weren't actually under the corresponding feature --- .../Modules/Orchard.Email/Activities/EmailActivity.cs | 2 +- src/Orchard.Web/Modules/Orchard.Email/Forms/EmailForm.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Email/Activities/EmailActivity.cs b/src/Orchard.Web/Modules/Orchard.Email/Activities/EmailActivity.cs index 2e5c7b69f..ccb8f16ec 100644 --- a/src/Orchard.Web/Modules/Orchard.Email/Activities/EmailActivity.cs +++ b/src/Orchard.Web/Modules/Orchard.Email/Activities/EmailActivity.cs @@ -12,7 +12,7 @@ namespace Orchard.Email.Activities { void Enqueue(string message, object parameters, int priority); } - [OrchardSuppressDependency("Orchard.Email.Workflows")] + [OrchardFeature("Orchard.Email.Workflows")] public class EmailActivity : Task { private readonly IMessageService _messageService; private readonly IJobsQueueService _jobsQueueService; diff --git a/src/Orchard.Web/Modules/Orchard.Email/Forms/EmailForm.cs b/src/Orchard.Web/Modules/Orchard.Email/Forms/EmailForm.cs index f1a438fd5..9e790159f 100644 --- a/src/Orchard.Web/Modules/Orchard.Email/Forms/EmailForm.cs +++ b/src/Orchard.Web/Modules/Orchard.Email/Forms/EmailForm.cs @@ -10,7 +10,7 @@ using Orchard.Localization; namespace Orchard.Email.Forms { - [OrchardSuppressDependency("Orchard.Email.Workflows")] + [OrchardFeature("Orchard.Email.Workflows")] public class EmailForm : Component, IFormProvider { private readonly IFeatureManager _featureManager; protected dynamic New { get; set; } From 2a57a153632d31a8692f2ad437e6d5e897e33c79 Mon Sep 17 00:00:00 2001 From: Lombiq Date: Wed, 20 May 2015 01:31:15 +0200 Subject: [PATCH 63/73] Fixing that in Workflows localized outcomes were used as identifiers, breaking when a localization package was installed. This is a breaking change for localized sites, see 1.10 release notes. --- .../Scripts/orchard-workflows-serialize.js | 2 +- .../Orchard.Workflows/Scripts/orchard-workflows.js | 10 +++++----- .../Orchard.Workflows/Views/ActivityToolbox.cshtml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Workflows/Scripts/orchard-workflows-serialize.js b/src/Orchard.Web/Modules/Orchard.Workflows/Scripts/orchard-workflows-serialize.js index 7d295bad0..268665fa6 100644 --- a/src/Orchard.Web/Modules/Orchard.Workflows/Scripts/orchard-workflows-serialize.js +++ b/src/Orchard.Web/Modules/Orchard.Workflows/Scripts/orchard-workflows-serialize.js @@ -26,7 +26,7 @@ var saveLocal = function (localId) { workflow.Connections.push({ SourceId: connection.sourceId, TargetId: connection.targetId, - SourceEndpoint: connection.endpoints[0].outcome, + SourceEndpoint: connection.endpoints[0].outcome.Id, //targetEndpoint: connection.targetEndpoint }); } diff --git a/src/Orchard.Web/Modules/Orchard.Workflows/Scripts/orchard-workflows.js b/src/Orchard.Web/Modules/Orchard.Workflows/Scripts/orchard-workflows.js index ad3bf9e01..776d959b3 100644 --- a/src/Orchard.Web/Modules/Orchard.Workflows/Scripts/orchard-workflows.js +++ b/src/Orchard.Web/Modules/Orchard.Workflows/Scripts/orchard-workflows.js @@ -81,7 +81,7 @@ displaySaveMessage(); } }); - + $("#search-box").focus().on("keyup", function (e) { var text = $(this).val(); if (text == "") { @@ -155,13 +155,13 @@ for (i = 0; i < outcomes.length; i++) { var ep = jsPlumb.addEndpoint(dom, { anchor: "Continuous", - connectorOverlays: [["Label", { label: outcomes[i].label, cssClass: "connection-label" }]], + connectorOverlays: [["Label", { label: outcomes[i].Label, cssClass: "connection-label" }]], }, sourceEndpointOptions); - elt.endpoints[outcomes[i].value] = ep; - ep.outcome = outcomes[i].value; - // ep.overlays[0].setLabel(outcomes[i]); + elt.endpoints[outcomes[i].Id] = ep; + ep.outcome = outcomes[i]; + // ep.overlays[0].setLabel(outcomes[i].Label); } if (activities[name].hasForm) { diff --git a/src/Orchard.Web/Modules/Orchard.Workflows/Views/ActivityToolbox.cshtml b/src/Orchard.Web/Modules/Orchard.Workflows/Views/ActivityToolbox.cshtml index 9c6b3ed25..1fdb440c4 100644 --- a/src/Orchard.Web/Modules/Orchard.Workflows/Views/ActivityToolbox.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Workflows/Views/ActivityToolbox.cshtml @@ -1,4 +1,4 @@ -@using Orchard.Utility.Extensions +@using Orchard.Utility.Extensions @using Orchard.Workflows.Models @using Orchard.Workflows.Services @@ -12,7 +12,7 @@
          @foreach (var activity in allActivities) { -
        • +
        • @activity.Name.CamelFriendly()

          @activity.Description @@ -27,7 +27,7 @@ // '@activity.Name': { - outcomes: [@Html.Raw(String.Join(",", activity.GetPossibleOutcomes(new WorkflowContext(), new ActivityContext()).Where(x => !String.IsNullOrEmpty(x.Text)).Select(x => "{label:'" + HttpUtility.JavaScriptStringEncode(x.Text) + "', value:'" + HttpUtility.JavaScriptStringEncode(x.TextHint) + "'}").ToArray()))], + outcomes: [@Html.Raw(String.Join(",", activity.GetPossibleOutcomes(new WorkflowContext(), new ActivityContext()).Where(x => !String.IsNullOrEmpty(x.Text)).Select(x => "{ Id: '" + HttpUtility.JavaScriptStringEncode(x.TextHint) + "', Label: '" + HttpUtility.JavaScriptStringEncode(x.Text) + "' }").ToArray()))], category: '@HttpUtility.JavaScriptStringEncode(activity.Category.Text)', description: '@HttpUtility.JavaScriptStringEncode(activity.Description.Text)', IsEvent: @(activity.IsEvent ? "true" : "false"), From c3c8edf300bfac0644c0e0ab6c06b61dc0c49044 Mon Sep 17 00:00:00 2001 From: Bertrand Le Roy Date: Wed, 20 May 2015 17:33:55 -0700 Subject: [PATCH 64/73] Move the chat badge down on readme. --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 30435469d..9f635731a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ # Orchard -[![Join the chat at https://gitter.im/OrchardCMS/Orchard](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/OrchardCMS/Orchard?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) Orchard is a free, open source, community-focused Content Management System built on the ASP.NET MVC platform. +[![Join the chat at https://gitter.im/OrchardCMS/Orchard](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/OrchardCMS/Orchard?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + ## About The Orchard Project #### Please visit our website at http://orchardproject.net for the most current information about this project. From 8976cc11d1114b8df0c9b5d8157851b3deb49bc7 Mon Sep 17 00:00:00 2001 From: Bertrand Le Roy Date: Wed, 20 May 2015 17:38:37 -0700 Subject: [PATCH 65/73] Update Readme to reflect the most recent mission statement and version number. --- README.md | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 9f635731a..20ccb5a89 100644 --- a/README.md +++ b/README.md @@ -8,23 +8,19 @@ Orchard is a free, open source, community-focused Content Management System buil #### Please visit our website at http://orchardproject.net for the most current information about this project. -Orchard is a free, open source, community-focused project aimed at delivering applications and reusable components -on the ASP.NET platform. It will create shared components for building ASP.NET applications and extensions, and -specific applications that leverage these components to meet the needs of end-users, scripters, and developers. -Additionally, we seek to create partnerships with existing application authors to help them achieve their goals. -Orchard is delivered under the [.NET Foundation](http://www.dotnetfoundation.org/). It is licensed under a -[New BSD license](http://www.opensource.org/licenses/bsd-license.php), which is approved by the OSI. The intended -output of the Orchard project is three-fold: +Orchard is a free, open source, community-focused Content Management System built on the ASP.NET MVC platform. -* Individual .NET-based applications that appeal to end-users, scripters, and developers -* A set of re-usable components that makes it easy to build such applications -* A vibrant community to help define these applications and extensions -In the near term, the Orchard project is focused on delivering a .NET-based CMS application that will allow users -to rapidly create content-driven Websites, and an extensibility framework that will allow developers and customizers to provide additional functionality through modules and themes. You can learn more about the project on the [Orchard Project Website](http://www.orchardproject.net). +Orchard is built on a modern architecture that puts extensibility up-front, as its number one concern. All components in Orchard can be replaced or extended. Content is built from easily composable building blocks. Modules extend the system in a very decoupled fashion, where a commenting module for example can as easily apply to pages, blog posts, photos or products. A rich UI composition system completes the picture and ensures that you can get the exact presentation that you need for your content. + +Orchard is delivered under the .NET Foundation. It is licensed under a New BSD license, which is approved by the OSI. + +Our mission is to empower our users and foster a dedicated and diverse community that builds the CMS that we all want to use. + +There are many ways you can contribute to Orchard: you can fix bugs, contribute modules and themes to our gallery, write documentation, translate Orchard, or answer questions on our forums and on Stack Overflow. ## Project Status -Orchard is currently in version 1.8.1. We invite participation by the developer community in shaping the project’s direction, so that we can publicly validate our designs and development approach. -Our 1.8.1 release is available from our Downloads page, and is easy to [Install Orchard using the Web Platform Installer](http://www.orchardproject.net/docs/Installing-Orchard.ashx). We encourage interested developers to check out the source code on the Orchard Github site and get involved with the project. +Orchard is currently in version 1.9. We invite participation by the developer community in shaping the project’s direction, so that we can publicly validate our designs and development approach. +Our 1.9 release is available from [our Downloads page](https://github.com/OrchardCMS/Orchard/releases), and is easy to [Install Orchard using the Web Platform Installer](http://www.orchardproject.net/docs/Installing-Orchard.ashx). We encourage interested developers to check out the source code on the Orchard Github site and get involved with the project. * [Download the latest release](https://github.com/OrchardCMS/Orchard/releases) * [Feature roadmap](http://www.orchardproject.net/docs/feature-roadmap.ashx) From 5f30667df18dacf73ea2f9b7210ae22086a2d479 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Thu, 21 May 2015 13:47:14 +0200 Subject: [PATCH 66/73] #5309: Updated OutputCacheFilter to include a check for the OutputCacheAttribute.Location value. --- .../Filters/OutputCacheFilter.cs | 4 +++- .../Helpers/OutputCacheAttributeExtensions.cs | 14 ++++++++++++++ .../Orchard.OutputCache/Orchard.OutputCache.csproj | 1 + 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/Orchard.Web/Modules/Orchard.OutputCache/Helpers/OutputCacheAttributeExtensions.cs diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs index f93e4c855..a44a443e3 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs @@ -11,12 +11,14 @@ using System.Threading; using System.Web; using System.Web.Mvc; using System.Web.Routing; +using System.Web.UI; using Orchard.Caching; using Orchard.ContentManagement; using Orchard.Environment.Configuration; using Orchard.Logging; using Orchard.Mvc.Extensions; using Orchard.Mvc.Filters; +using Orchard.OutputCache.Helpers; using Orchard.OutputCache.Models; using Orchard.OutputCache.Services; using Orchard.Services; @@ -263,7 +265,7 @@ namespace Orchard.OutputCache.Filters { var controllerAttributes = filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(OutputCacheAttribute), true); var outputCacheAttribute = actionAttributes.Concat(controllerAttributes).Cast().FirstOrDefault(); if (outputCacheAttribute != null) { - if (outputCacheAttribute.Duration <= 0 || outputCacheAttribute.NoStore) { + if (outputCacheAttribute.Duration <= 0 || outputCacheAttribute.NoStore || outputCacheAttribute.IsLocationAnyOf(OutputCacheLocation.Downstream, OutputCacheLocation.Client, OutputCacheLocation.None)) { Logger.Debug("Request for item '{0}' ignored based on OutputCache attribute.", _cacheKey); return false; } diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Helpers/OutputCacheAttributeExtensions.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Helpers/OutputCacheAttributeExtensions.cs new file mode 100644 index 000000000..b34a16b8c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Helpers/OutputCacheAttributeExtensions.cs @@ -0,0 +1,14 @@ +using System.Linq; +using System.Web.Mvc; +using System.Web.UI; + +namespace Orchard.OutputCache.Helpers { + public static class OutputCacheAttributeExtensions { + /// + /// Returns true if the Location of the specified output cache attribute matches any of the specified list of locations. + /// + public static bool IsLocationAnyOf(this OutputCacheAttribute attribute, params OutputCacheLocation[] locations) { + return locations.Any(x => attribute.Location == x); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Orchard.OutputCache.csproj b/src/Orchard.Web/Modules/Orchard.OutputCache/Orchard.OutputCache.csproj index 41e412c22..8a7429e9e 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Orchard.OutputCache.csproj +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Orchard.OutputCache.csproj @@ -102,6 +102,7 @@ + From f5b9a76675ace6f06ea1cf6202349a5104d10b90 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Thu, 21 May 2015 13:53:55 +0200 Subject: [PATCH 67/73] #5309: Simplified implementation and renamed helper method. --- .../Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs | 2 +- .../Helpers/OutputCacheAttributeExtensions.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs index a44a443e3..5aaa07ad4 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs @@ -265,7 +265,7 @@ namespace Orchard.OutputCache.Filters { var controllerAttributes = filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(OutputCacheAttribute), true); var outputCacheAttribute = actionAttributes.Concat(controllerAttributes).Cast().FirstOrDefault(); if (outputCacheAttribute != null) { - if (outputCacheAttribute.Duration <= 0 || outputCacheAttribute.NoStore || outputCacheAttribute.IsLocationAnyOf(OutputCacheLocation.Downstream, OutputCacheLocation.Client, OutputCacheLocation.None)) { + if (outputCacheAttribute.Duration <= 0 || outputCacheAttribute.NoStore || outputCacheAttribute.LocationIsIn(OutputCacheLocation.Downstream, OutputCacheLocation.Client, OutputCacheLocation.None)) { Logger.Debug("Request for item '{0}' ignored based on OutputCache attribute.", _cacheKey); return false; } diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Helpers/OutputCacheAttributeExtensions.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Helpers/OutputCacheAttributeExtensions.cs index b34a16b8c..363c622ea 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Helpers/OutputCacheAttributeExtensions.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Helpers/OutputCacheAttributeExtensions.cs @@ -7,8 +7,8 @@ namespace Orchard.OutputCache.Helpers { /// /// Returns true if the Location of the specified output cache attribute matches any of the specified list of locations. /// - public static bool IsLocationAnyOf(this OutputCacheAttribute attribute, params OutputCacheLocation[] locations) { - return locations.Any(x => attribute.Location == x); + public static bool LocationIsIn(this OutputCacheAttribute attribute, params OutputCacheLocation[] locations) { + return locations.Contains(attribute.Location); } } } \ No newline at end of file From 0283dc22c5565998e4df4658749460b1fafb7647 Mon Sep 17 00:00:00 2001 From: Lombiq Date: Fri, 22 May 2015 00:18:24 +0200 Subject: [PATCH 68/73] Warning users when they remove the home page, fixes #4843 --- .../Handlers/AutoroutePartHandler.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Orchard.Web/Modules/Orchard.Autoroute/Handlers/AutoroutePartHandler.cs b/src/Orchard.Web/Modules/Orchard.Autoroute/Handlers/AutoroutePartHandler.cs index ef3e8ca14..4f7fce25b 100644 --- a/src/Orchard.Web/Modules/Orchard.Autoroute/Handlers/AutoroutePartHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Autoroute/Handlers/AutoroutePartHandler.cs @@ -7,23 +7,27 @@ using Orchard.Data; using Orchard.Autoroute.Services; using Orchard.Localization; using Orchard.UI.Notify; +using Orchard.Alias; namespace Orchard.Autoroute.Handlers { public class AutoroutePartHandler : ContentHandler { private readonly Lazy _autorouteService; private readonly IOrchardServices _orchardServices; + private readonly IAliasService _aliasService; public Localizer T { get; set; } public AutoroutePartHandler( IRepository autoroutePartRepository, Lazy autorouteService, - IOrchardServices orchardServices) { + IOrchardServices orchardServices, + IAliasService aliasService) { Filters.Add(StorageFilter.For(autoroutePartRepository)); _autorouteService = autorouteService; _orchardServices = orchardServices; + _aliasService = aliasService; OnUpdated((ctx, part) => CreateAlias(part)); @@ -97,6 +101,13 @@ namespace Orchard.Autoroute.Handlers { } void RemoveAlias(AutoroutePart part) { + // Is this the current home page? + var homePageRoute = _aliasService.Get(""); + var homePageId = homePageRoute.ContainsKey("id") ? int.Parse(homePageRoute["id"].ToString()) : default(int); + + if (part.ContentItem.Id == homePageId) { + _orchardServices.Notifier.Warning(T("You removed the content item that served as the site\'s home page. \nMost possibly this means that instead of the home page a \"404 Not Found\" error page will be displayed without a link to log in or access the dashboard. \n\nTo prevent this you can e.g. publish a content item that has the \"Set as home page\" checkbox ticked.")); + } _autorouteService.Value.RemoveAliases(part); } } From d1ae7380e49067f965d81c412f39997c5ce44e96 Mon Sep 17 00:00:00 2001 From: Lombiq Date: Fri, 22 May 2015 00:19:16 +0200 Subject: [PATCH 69/73] Removing empty Controllers folder from Autoroute --- .../Modules/Orchard.Autoroute/Orchard.Autoroute.csproj | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Autoroute/Orchard.Autoroute.csproj b/src/Orchard.Web/Modules/Orchard.Autoroute/Orchard.Autoroute.csproj index c6aec01b5..d2f05b926 100644 --- a/src/Orchard.Web/Modules/Orchard.Autoroute/Orchard.Autoroute.csproj +++ b/src/Orchard.Web/Modules/Orchard.Autoroute/Orchard.Autoroute.csproj @@ -122,9 +122,7 @@ - - - + Designer From 09d232612ac99d7ea93c517f7a149dfc3c205a95 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sat, 23 May 2015 11:09:41 +0200 Subject: [PATCH 70/73] Removed unused enum values and consolidated SortDirection and OrderByDirection. The unused enum values of the SortDirectionEnum were probably an artifact of a copy/paste operation. --- src/Orchard.Web/Core/Containers/Models/OrderByDirection.cs | 6 ------ .../Core/Containers/ViewModels/ContainerViewModel.cs | 4 +--- .../Containers/Views/EditorTemplates/ContainerWidget.cshtml | 5 ++--- src/Orchard.Web/Core/Orchard.Core.csproj | 1 - 4 files changed, 3 insertions(+), 13 deletions(-) delete mode 100644 src/Orchard.Web/Core/Containers/Models/OrderByDirection.cs diff --git a/src/Orchard.Web/Core/Containers/Models/OrderByDirection.cs b/src/Orchard.Web/Core/Containers/Models/OrderByDirection.cs deleted file mode 100644 index 3cc6e2697..000000000 --- a/src/Orchard.Web/Core/Containers/Models/OrderByDirection.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Orchard.Core.Containers.Models { - public enum OrderByDirection { - Ascending, - Descending - } -} diff --git a/src/Orchard.Web/Core/Containers/ViewModels/ContainerViewModel.cs b/src/Orchard.Web/Core/Containers/ViewModels/ContainerViewModel.cs index 65006a4eb..dd0bbb328 100644 --- a/src/Orchard.Web/Core/Containers/ViewModels/ContainerViewModel.cs +++ b/src/Orchard.Web/Core/Containers/ViewModels/ContainerViewModel.cs @@ -26,8 +26,6 @@ namespace Orchard.Core.Containers.ViewModels { public enum SortDirection { Ascending, - Descending, - Created, - DisplayText + Descending } } \ No newline at end of file diff --git a/src/Orchard.Web/Core/Containers/Views/EditorTemplates/ContainerWidget.cshtml b/src/Orchard.Web/Core/Containers/Views/EditorTemplates/ContainerWidget.cshtml index 9be03b722..46d201a50 100644 --- a/src/Orchard.Web/Core/Containers/Views/EditorTemplates/ContainerWidget.cshtml +++ b/src/Orchard.Web/Core/Containers/Views/EditorTemplates/ContainerWidget.cshtml @@ -1,5 +1,4 @@ @model Orchard.Core.Containers.ViewModels.ContainerWidgetViewModel -@using Orchard.Core.Containers.Models; @{ Script.Require("ShapesBase"); } @@ -25,8 +24,8 @@ @Html.SelectOption(Model.Part.Record.OrderByProperty, "CustomPropertiesPart.CustomThree", T("Custom 3").Text)
        diff --git a/src/Orchard.Web/Core/Orchard.Core.csproj b/src/Orchard.Web/Core/Orchard.Core.csproj index b7fbbb7ba..eaa488e62 100644 --- a/src/Orchard.Web/Core/Orchard.Core.csproj +++ b/src/Orchard.Web/Core/Orchard.Core.csproj @@ -117,7 +117,6 @@ - From 443b03fd67b410094df6fd18353536291e087380 Mon Sep 17 00:00:00 2001 From: Lombiq Date: Sat, 23 May 2015 21:49:41 +0200 Subject: [PATCH 71/73] Removing unused folders from TaskLease --- .../Orchard.TaskLease/Orchard.TaskLease.csproj | 6 +----- .../Modules/Orchard.TaskLease/Scripts/Web.config | 16 ---------------- .../Modules/Orchard.TaskLease/Styles/Web.config | 16 ---------------- 3 files changed, 1 insertion(+), 37 deletions(-) delete mode 100644 src/Orchard.Web/Modules/Orchard.TaskLease/Scripts/Web.config delete mode 100644 src/Orchard.Web/Modules/Orchard.TaskLease/Styles/Web.config diff --git a/src/Orchard.Web/Modules/Orchard.TaskLease/Orchard.TaskLease.csproj b/src/Orchard.Web/Modules/Orchard.TaskLease/Orchard.TaskLease.csproj index 358b87276..aeb29903f 100644 --- a/src/Orchard.Web/Modules/Orchard.TaskLease/Orchard.TaskLease.csproj +++ b/src/Orchard.Web/Modules/Orchard.TaskLease/Orchard.TaskLease.csproj @@ -72,8 +72,6 @@ - - @@ -85,9 +83,7 @@ - - - + {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} diff --git a/src/Orchard.Web/Modules/Orchard.TaskLease/Scripts/Web.config b/src/Orchard.Web/Modules/Orchard.TaskLease/Scripts/Web.config deleted file mode 100644 index 7806fcc84..000000000 --- a/src/Orchard.Web/Modules/Orchard.TaskLease/Scripts/Web.config +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/Orchard.Web/Modules/Orchard.TaskLease/Styles/Web.config b/src/Orchard.Web/Modules/Orchard.TaskLease/Styles/Web.config deleted file mode 100644 index 7806fcc84..000000000 --- a/src/Orchard.Web/Modules/Orchard.TaskLease/Styles/Web.config +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - From 801d58183a1be00c8c1a2519280a35bbf3e44f64 Mon Sep 17 00:00:00 2001 From: Lombiq Date: Sat, 23 May 2015 23:54:08 +0200 Subject: [PATCH 72/73] Fixing that JobsQueue doesn't actually use Task Lease to prevent multiple server nodes from executing the same jobs --- .../Orchard.JobsQueue/Services/JobsQueueProcessor.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.JobsQueue/Services/JobsQueueProcessor.cs b/src/Orchard.Web/Modules/Orchard.JobsQueue/Services/JobsQueueProcessor.cs index 085864810..958ef89d0 100644 --- a/src/Orchard.Web/Modules/Orchard.JobsQueue/Services/JobsQueueProcessor.cs +++ b/src/Orchard.Web/Modules/Orchard.JobsQueue/Services/JobsQueueProcessor.cs @@ -35,12 +35,13 @@ namespace Orchard.JobsQueue.Services { // prevent two threads on the same machine to process the message queue if (_rwl.TryEnterWriteLock(0)) { try { - _taskLeaseService.Value.Acquire("JobsQueueProcessor", _clock.Value.UtcNow.AddMinutes(5)); - IEnumerable messages; + if (_taskLeaseService.Value.Acquire("JobsQueueProcessor", _clock.Value.UtcNow.AddMinutes(5)) != null) { + IEnumerable messages; - while ((messages = _jobsQueueManager.Value.GetJobs(0, 10).ToArray()).Any()) { - foreach (var message in messages) { - ProcessMessage(message); + while ((messages = _jobsQueueManager.Value.GetJobs(0, 10).ToArray()).Any()) { + foreach (var message in messages) { + ProcessMessage(message); + } } } } From 9bf6ac5718b24dbac5be0d1a6abb690cd35e2b4f Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Tue, 26 May 2015 19:49:55 +0200 Subject: [PATCH 73/73] #4607: Refactored HttpContextAccessor to return a valid HttpContextBase instance in background tasks. --- .../Settings/Commands/SiteSettingsCommands.cs | 3 +- .../Implementation/DefaultDisplayManager.cs | 3 +- .../Environment/DefaultHostEnvironment.cs | 3 +- src/Orchard/Environment/OrchardStarter.cs | 2 +- .../Environment/WorkContextAccessor.cs | 5 +-- .../Extensions/HttpContextBaseExtensions.cs | 9 +++++ src/Orchard/Mvc/HttpContextAccessor.cs | 18 ++++++++++ src/Orchard/Mvc/IHttpContextAccessor.cs | 34 +------------------ src/Orchard/Mvc/MvcModule.cs | 8 ++--- src/Orchard/Orchard.Framework.csproj | 2 ++ .../Providers/FormsAuthenticationService.cs | 3 +- 11 files changed, 46 insertions(+), 44 deletions(-) create mode 100644 src/Orchard/Mvc/Extensions/HttpContextBaseExtensions.cs create mode 100644 src/Orchard/Mvc/HttpContextAccessor.cs diff --git a/src/Orchard.Web/Core/Settings/Commands/SiteSettingsCommands.cs b/src/Orchard.Web/Core/Settings/Commands/SiteSettingsCommands.cs index d3fcb8ca6..1778d48c3 100644 --- a/src/Orchard.Web/Core/Settings/Commands/SiteSettingsCommands.cs +++ b/src/Orchard.Web/Core/Settings/Commands/SiteSettingsCommands.cs @@ -2,6 +2,7 @@ using Orchard.ContentManagement; using Orchard.Core.Settings.Models; using Orchard.Mvc; +using Orchard.Mvc.Extensions; using Orchard.Settings; using Orchard.Utility.Extensions; @@ -38,7 +39,7 @@ namespace Orchard.Core.Settings.Commands { // Retrieve request URL if BaseUrl not provided as a switch value if (string.IsNullOrEmpty(BaseUrl)) { - if (_httpContextAccessor.Current() == null) { + if (_httpContextAccessor.Current().IsBackgroundContext()) { Context.Output.WriteLine(T("No HTTP request available to determine the base url of the site")); return; } diff --git a/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs b/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs index 29563b9c9..967ae91de 100644 --- a/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs +++ b/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs @@ -11,6 +11,7 @@ using Orchard.DisplayManagement.Shapes; using Orchard.Localization; using Orchard.Logging; using Orchard.Mvc; +using Orchard.Mvc.Extensions; namespace Orchard.DisplayManagement.Implementation { public class DefaultDisplayManager : IDisplayManager { @@ -61,7 +62,7 @@ namespace Orchard.DisplayManagement.Implementation { return CoerceHtmlString(context.Value); var workContext = _workContextAccessor.GetContext(); - var shapeTable = _httpContextAccessor.Current() != null + var shapeTable = !_httpContextAccessor.Current().IsBackgroundContext() ? _shapeTableLocator.Value.Lookup(workContext.CurrentTheme.Id) : _shapeTableLocator.Value.Lookup(null); diff --git a/src/Orchard/Environment/DefaultHostEnvironment.cs b/src/Orchard/Environment/DefaultHostEnvironment.cs index 37d6e6c49..b4c388029 100644 --- a/src/Orchard/Environment/DefaultHostEnvironment.cs +++ b/src/Orchard/Environment/DefaultHostEnvironment.cs @@ -3,6 +3,7 @@ using System.Web; using Orchard.Localization; using Orchard.Logging; using Orchard.Mvc; +using Orchard.Mvc.Extensions; using Orchard.Services; using Orchard.Utility.Extensions; @@ -41,7 +42,7 @@ namespace Orchard.Environment { // current request can be processed correctly. So, we redirect to the same URL, so that the // new request will come to the newly started AppDomain. var httpContext = _httpContextAccessor.Current(); - if (httpContext != null) { + if (!httpContext.IsBackgroundContext()) { // Don't redirect posts... if (httpContext.Request.RequestType == "GET") { httpContext.Response.Redirect(HttpContext.Current.Request.ToUrlString(), true /*endResponse*/); diff --git a/src/Orchard/Environment/OrchardStarter.cs b/src/Orchard/Environment/OrchardStarter.cs index 66ea2a066..3dbd599d9 100644 --- a/src/Orchard/Environment/OrchardStarter.cs +++ b/src/Orchard/Environment/OrchardStarter.cs @@ -63,7 +63,7 @@ namespace Orchard.Environment { builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); - builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As().InstancePerDependency(); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); diff --git a/src/Orchard/Environment/WorkContextAccessor.cs b/src/Orchard/Environment/WorkContextAccessor.cs index a1216f644..af709d0d5 100644 --- a/src/Orchard/Environment/WorkContextAccessor.cs +++ b/src/Orchard/Environment/WorkContextAccessor.cs @@ -5,6 +5,7 @@ using System.Web; using Autofac; using Orchard.Logging; using Orchard.Mvc; +using Orchard.Mvc.Extensions; namespace Orchard.Environment { public class WorkContextAccessor : IWorkContextAccessor { @@ -31,7 +32,7 @@ namespace Orchard.Environment { public WorkContext GetContext() { var httpContext = _httpContextAccessor.Current(); - if (httpContext != null) + if (!httpContext.IsBackgroundContext()) return GetContext(httpContext); WorkContext workContext; @@ -55,7 +56,7 @@ namespace Orchard.Environment { public IWorkContextScope CreateWorkContextScope() { var httpContext = _httpContextAccessor.Current(); - if (httpContext != null) + if (!httpContext.IsBackgroundContext()) return CreateWorkContextScope(httpContext); var workLifetime = _lifetimeScope.BeginLifetimeScope("work"); diff --git a/src/Orchard/Mvc/Extensions/HttpContextBaseExtensions.cs b/src/Orchard/Mvc/Extensions/HttpContextBaseExtensions.cs new file mode 100644 index 000000000..9a7864887 --- /dev/null +++ b/src/Orchard/Mvc/Extensions/HttpContextBaseExtensions.cs @@ -0,0 +1,9 @@ +using System.Web; + +namespace Orchard.Mvc.Extensions { + public static class HttpContextBaseExtensions { + public static bool IsBackgroundContext(this HttpContextBase httpContextBase) { + return httpContextBase == null || httpContextBase is MvcModule.HttpContextPlaceholder; + } + } +} diff --git a/src/Orchard/Mvc/HttpContextAccessor.cs b/src/Orchard/Mvc/HttpContextAccessor.cs new file mode 100644 index 000000000..ffea8ca66 --- /dev/null +++ b/src/Orchard/Mvc/HttpContextAccessor.cs @@ -0,0 +1,18 @@ +using System.Web; +using Autofac; + +namespace Orchard.Mvc { + public class HttpContextAccessor : IHttpContextAccessor { + private readonly IComponentContext _context; + + public HttpContextAccessor(IComponentContext context) { + _context = context; + } + + public HttpContextBase Current() { + HttpContextBase httpContextBase; + _context.TryResolve(out httpContextBase); + return httpContextBase; + } + } +} \ No newline at end of file diff --git a/src/Orchard/Mvc/IHttpContextAccessor.cs b/src/Orchard/Mvc/IHttpContextAccessor.cs index 91208d314..d456bce2e 100644 --- a/src/Orchard/Mvc/IHttpContextAccessor.cs +++ b/src/Orchard/Mvc/IHttpContextAccessor.cs @@ -1,39 +1,7 @@ -using System; -using System.Web; +using System.Web; namespace Orchard.Mvc { public interface IHttpContextAccessor { HttpContextBase Current(); - void Set(HttpContextBase httpContext); - } - - public class HttpContextAccessor : IHttpContextAccessor { - private HttpContextBase _httpContext; - - public HttpContextBase Current() { - var httpContext = GetStaticProperty(); - return httpContext != null ? new HttpContextWrapper(httpContext) : _httpContext; - } - - public void Set(HttpContextBase httpContext) { - _httpContext = httpContext; - } - - private HttpContext GetStaticProperty() { - var httpContext = HttpContext.Current; - if (httpContext == null) { - return null; - } - - try { - if (httpContext.Request == null) { - return null; - } - } - catch (Exception) { - return null; - } - return httpContext; - } } } diff --git a/src/Orchard/Mvc/MvcModule.cs b/src/Orchard/Mvc/MvcModule.cs index 1e0c49ce6..d6e7db059 100644 --- a/src/Orchard/Mvc/MvcModule.cs +++ b/src/Orchard/Mvc/MvcModule.cs @@ -85,7 +85,7 @@ namespace Orchard.Mvc { /// /// Standin context for background tasks. /// - class HttpContextPlaceholder : HttpContextBase { + public class HttpContextPlaceholder : HttpContextBase { private readonly Lazy _baseUrl; private readonly IDictionary _items = new Dictionary(); @@ -120,7 +120,7 @@ namespace Orchard.Mvc { } } - private class HttpResponsePlaceholder : HttpResponseBase { + public class HttpResponsePlaceholder : HttpResponseBase { public override string ApplyAppPathModifier(string virtualPath) { return virtualPath; } @@ -135,7 +135,7 @@ namespace Orchard.Mvc { /// /// standin context for background tasks. /// - class HttpRequestPlaceholder : HttpRequestBase { + public class HttpRequestPlaceholder : HttpRequestBase { private readonly Uri _uri; public HttpRequestPlaceholder(Uri uri) { @@ -217,7 +217,7 @@ namespace Orchard.Mvc { } } - class HttpBrowserCapabilitiesPlaceholder : HttpBrowserCapabilitiesBase { + public class HttpBrowserCapabilitiesPlaceholder : HttpBrowserCapabilitiesBase { public override string this[string key] { get { return ""; diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index 7a3ce7d31..c53e885c9 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -317,7 +317,9 @@ + + diff --git a/src/Orchard/Security/Providers/FormsAuthenticationService.cs b/src/Orchard/Security/Providers/FormsAuthenticationService.cs index 58ad7c9b9..b31b04b5c 100644 --- a/src/Orchard/Security/Providers/FormsAuthenticationService.cs +++ b/src/Orchard/Security/Providers/FormsAuthenticationService.cs @@ -5,6 +5,7 @@ using Orchard.Environment.Configuration; using Orchard.Logging; using Orchard.ContentManagement; using Orchard.Mvc; +using Orchard.Mvc.Extensions; using Orchard.Services; namespace Orchard.Security.Providers { @@ -102,7 +103,7 @@ namespace Orchard.Security.Providers { return _signedInUser; var httpContext = _httpContextAccessor.Current(); - if (httpContext == null || !httpContext.Request.IsAuthenticated || !(httpContext.User.Identity is FormsIdentity)) { + if (httpContext.IsBackgroundContext() || !httpContext.Request.IsAuthenticated || !(httpContext.User.Identity is FormsIdentity)) { return null; }