diff --git a/.gitignore b/.gitignore index 18cf32456..747685453 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.suo *.user *.sln.docstates +*.sln.ide/ # Build results diff --git a/ClickToBuild.cmd b/ClickToBuild.cmd index fa64a26f8..3c0b68c2d 100644 --- a/ClickToBuild.cmd +++ b/ClickToBuild.cmd @@ -1,32 +1,33 @@ -if "%WindowsSdkDir%" neq "" goto build -if exist "%ProgramFiles%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" goto initialize2k8Dev12 -if exist "%ProgramFiles(x86)%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" goto initialize2k8on64Dev12 -if exist "%ProgramFiles%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" goto initialize2k8Dev11 -if exist "%ProgramFiles(x86)%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" goto initialize2k8on64Dev11 +if exist "%ProgramFiles%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" goto initialize2k8on64Dev12 +if exist "%ProgramFiles(x86)%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" goto initialize2k8Dev12 +if exist "%ProgramFiles%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" goto initialize2k8on64Dev11 +if exist "%ProgramFiles(x86)%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" goto initialize2k8Dev11 echo "Unable to detect suitable environment. Build may not succeed." goto build :initialize2k8Dev12 -call "%ProgramFiles%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86 -goto build - -:initialize2k8on64Dev12 call "%ProgramFiles(x86)%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86 goto build -:initialize2k8Dev11 -call "%ProgramFiles%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" x86 +:initialize2k8on64Dev12 +call "%ProgramFiles%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86 goto build -:initialize2k8on64Dev11 +:initialize2k8Dev11 call "%ProgramFiles(x86)%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" x86 goto build +:initialize2k8on64Dev11 +call "%ProgramFiles%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" x86 +goto build + :build -call build +if "%~1"=="" msbuild /t:Build Orchard.proj +msbuild /t:%~1 Orchard.proj + pause goto end diff --git a/ClickToBuildAzurePackage.cmd b/ClickToBuildAzurePackage.cmd index 004332e44..89f5cba72 100644 --- a/ClickToBuildAzurePackage.cmd +++ b/ClickToBuildAzurePackage.cmd @@ -1,30 +1,33 @@ -if "%WindowsSdkDir%" neq "" goto build -if exist "%ProgramFiles(x86)%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" goto initialize2k8on64Dev11 -if exist "%ProgramFiles%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" goto initialize2k8Dev11 -if exist "%ProgramFiles(x86)%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" goto initialize2k8on64Dev12 -if exist "%ProgramFiles%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" goto initialize2k8Dev12 + +if exist "%ProgramFiles%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" goto initialize2k8on64Dev12 +if exist "%ProgramFiles(x86)%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" goto initialize2k8Dev12 +if exist "%ProgramFiles%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" goto initialize2k8on64Dev11 +if exist "%ProgramFiles(x86)%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" goto initialize2k8Dev11 + echo "Unable to detect suitable environment. Build may not succeed." goto build :initialize2k8Dev12 -call "%ProgramFiles%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86 -goto build - -:initialize2k8on64Dev12 call "%ProgramFiles(x86)%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86 goto build -:initialize2k8Dev11 -call "%ProgramFiles%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" x86 +:initialize2k8on64Dev12 +call "%ProgramFiles%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86 goto build -:initialize2k8on64Dev11 +:initialize2k8Dev11 call "%ProgramFiles(x86)%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" x86 goto build +:initialize2k8on64Dev11 +call "%ProgramFiles%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" x86 +goto build + :build -msbuild /t:Build AzurePackage.proj +if "%~1"=="" msbuild /t:Build AzurePackage.proj +msbuild /t:%~1 AzurePackage.proj + pause goto end diff --git a/build.cmd b/build.cmd index eeddd1991..97f51bea8 100644 --- a/build.cmd +++ b/build.cmd @@ -1,3 +1,2 @@ -if "%~1"=="" build Build -msbuild /t:%~1 Orchard.proj - +if "%~1"=="" call clicktobuild +call clicktobuild %~1 \ No newline at end of file diff --git a/src/Orchard.Specs/Comments.feature b/src/Orchard.Specs/Comments.feature index 7c27734a3..22ca0eb1b 100644 --- a/src/Orchard.Specs/Comments.feature +++ b/src/Orchard.Specs/Comments.feature @@ -39,6 +39,7 @@ Scenario: HTML markup in any given comment is encoded And I hit "Submit Comment" And I am redirected # because the ToUrlString extension method breaks in this specific (test) environment, the returnUrl is broken... + And I go to "my-blog/my-post" # And I go to "my-blog/my-post" Then I should see "This is<br id="bad-anon-br" />a <a href" And I should not see "
" diff --git a/src/Orchard.Specs/Comments.feature.cs b/src/Orchard.Specs/Comments.feature.cs index 268618841..4c48a16bb 100644 --- a/src/Orchard.Specs/Comments.feature.cs +++ b/src/Orchard.Specs/Comments.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.0 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -150,11 +150,13 @@ this.ScenarioSetup(scenarioInfo); testRunner.And("I hit \"Submit Comment\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 40 testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); -#line 43 - testRunner.Then("I should see \"This is<br id="bad-anon-br" />a <a href\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line 42 + testRunner.And("I go to \"my-blog/my-post\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 44 + testRunner.Then("I should see \"This is<br id="bad-anon-br" />a <a href\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line 45 testRunner.And("I should not see \"
\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); -#line 47 +#line 48 testRunner.When("I go to \"users/account/logon\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table5 = new TechTalk.SpecFlow.Table(new string[] { @@ -166,13 +168,13 @@ this.ScenarioSetup(scenarioInfo); table5.AddRow(new string[] { "password", "6655321"}); -#line 48 +#line 49 testRunner.And("I fill in", ((string)(null)), table5, "And "); -#line 52 - testRunner.And("I hit \"Sign In\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 53 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Sign In\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 54 + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line 55 testRunner.And("I go to \"admin/settings/comments\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table6 = new TechTalk.SpecFlow.Table(new string[] { @@ -181,17 +183,17 @@ this.ScenarioSetup(scenarioInfo); table6.AddRow(new string[] { "CommentSettings.ModerateComments", "true"}); -#line 55 +#line 56 testRunner.And("I fill in", ((string)(null)), table6, "And "); -#line 58 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 59 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 60 - testRunner.Then("I should see \"Settings updated\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 61 - testRunner.When("I go to \"users/account/logoff\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.Then("I should see \"Settings updated\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 62 + testRunner.When("I go to \"users/account/logoff\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line 63 testRunner.And("I go to \"my-blog/my-post\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table7 = new TechTalk.SpecFlow.Table(new string[] { @@ -203,17 +205,17 @@ this.ScenarioSetup(scenarioInfo); table7.AddRow(new string[] { "Comments.CommentText", "This is a moderated comment."}); -#line 63 +#line 64 testRunner.And("I fill in", ((string)(null)), table7, "And "); -#line 67 - testRunner.And("I hit \"Submit Comment\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 68 + testRunner.And("I hit \"Submit Comment\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line 69 testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); -#line 70 - testRunner.And("I go to \"my-blog/my-post\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 71 - testRunner.Then("I should see \"Hi there\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.And("I go to \"my-blog/my-post\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 72 + testRunner.Then("I should see \"Hi there\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line 73 testRunner.And("I should not see \"This is a moderated comment\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden this.ScenarioCleanup(); diff --git a/src/Orchard.Tests/DataMigration/DataMigrationTests.cs b/src/Orchard.Tests/DataMigration/DataMigrationTests.cs index 3837d5dd8..607139767 100644 --- a/src/Orchard.Tests/DataMigration/DataMigrationTests.cs +++ b/src/Orchard.Tests/DataMigration/DataMigrationTests.cs @@ -237,6 +237,24 @@ namespace Orchard.Tests.DataMigration { return 3; } } + + public class FailingDataMigration : DataMigrationImpl { + public override Feature Feature { + get { return new Feature() { Descriptor = new FeatureDescriptor { Id = "Feature4", Extension = new ExtensionDescriptor { Id = "Module4" } } }; } + } + + public int Create() { + SchemaBuilder.CreateTable("FOO", table => + table.Column("Id", DbType.Int32, column => + column.PrimaryKey().Identity())); + + return 1; + } + + public int UpdateFrom1() { + throw new Exception(); + } + } public class DataMigrationSimpleBuilder : DataMigrationImpl { public override Feature Feature { @@ -471,9 +489,28 @@ Features: Description: Feature "); - _dataMigrationManager.Update("Feature1"); + try {_dataMigrationManager.Update("Feature1"); } + catch (OrchardException) {} + Assert.That(_repository.Table.Count(), Is.EqualTo(0)); + _dataMigrationManager.Update("Feature1"); } + + [Test] + public void FailingDataMigrationShouldThrowOrchardException() { + Init(new[] { typeof(FailingDataMigration) }); + + _folders.Manifests.Add("Module4", @" +Name: Module4 +Version: 0.1 +OrchardVersion: 1 +Features: + Feature4: + Description: Feature +"); + + Assert.Throws(() => _dataMigrationManager.Update("Feature4")); + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Email/Services/MissingSettingsBanner.cs b/src/Orchard.Web/Modules/Orchard.Email/Services/MissingSettingsBanner.cs index c91e66f85..9c627bbf8 100644 --- a/src/Orchard.Web/Modules/Orchard.Email/Services/MissingSettingsBanner.cs +++ b/src/Orchard.Web/Modules/Orchard.Email/Services/MissingSettingsBanner.cs @@ -22,8 +22,6 @@ namespace Orchard.Email.Services { var workContext = _orchardServices.WorkContext; var smtpSettings = workContext.CurrentSite.As(); - var smtpClient = new SmtpClient(); - if (smtpSettings == null || !smtpSettings.IsValid()) { var urlHelper = new UrlHelper(workContext.HttpContext.Request.RequestContext); var url = urlHelper.Action("Email", "Admin", new {Area = "Settings"}); diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Views/Admin/Export.cshtml b/src/Orchard.Web/Modules/Orchard.ImportExport/Views/Admin/Export.cshtml index 9c5a5dd8f..8f76081c1 100644 --- a/src/Orchard.Web/Modules/Orchard.ImportExport/Views/Admin/Export.cshtml +++ b/src/Orchard.Web/Modules/Orchard.ImportExport/Views/Admin/Export.cshtml @@ -5,10 +5,10 @@ @using (Html.BeginFormAntiForgeryPost()) { Html.ValidationSummary(); -
- @T("Choose the types to include in the export file:") -
    - @{var contentTypeIndex = 0;} +
    + @T("Choose the types to include in the export file:") +
      + @{var contentTypeIndex = 0;} @foreach (var contentTypeEntry in Model.ContentTypes) {
    1. @@ -17,7 +17,7 @@
    2. contentTypeIndex = contentTypeIndex + 1; } -
    +

diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs index 9fbf042a3..d4de846b8 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs @@ -12,6 +12,8 @@ namespace Orchard.Indexing.Settings { private readonly IIndexingTaskManager _indexingTaskManager; private readonly IContentManager _contentManager; + private const int PageSize = 50; + public EditorEvents(IIndexingTaskManager indexingTaskManager, IContentManager contentManager){ _indexingTaskManager = indexingTaskManager; _contentManager = contentManager; @@ -91,13 +93,15 @@ namespace Orchard.Indexing.Settings { do { contentItemProcessed = false; - var contentItemsToIndex = _contentManager.Query(VersionOptions.Latest, new [] { type }).Slice(index, 50); + 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); } } diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs index 84a178432..8806abfdf 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs @@ -221,7 +221,10 @@ namespace Orchard.Modules.Controllers { _moduleService.DisableFeatures(enabledFeatures, force == true); break; case FeaturesBulkAction.Update: - foreach (var feature in selectedFeatures.Where(x => x.NeedsUpdate)) { + var featuresThatNeedUpdate = _dataMigrationManager.GetFeaturesThatNeedUpdate(); + var selectedFeaturesThatNeedUpdate = selectedFeatures.Where(x => featuresThatNeedUpdate.Contains(x.Descriptor.Id)); + + foreach (var feature in selectedFeaturesThatNeedUpdate) { var id = feature.Descriptor.Id; try { _reportsCoordinator.Register("Data Migration", "Upgrade " + id, "Orchard installation"); diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs index e6b75389a..c0682f5f1 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs @@ -19,10 +19,12 @@ using Orchard.Mvc.Filters; using Orchard.Services; using Orchard.Themes; using Orchard.UI.Admin; +using Orchard.UI.Notify; using Orchard.Utility.Extensions; using System.Collections.Specialized; using Orchard.OutputCache.ViewModels; using Orchard.UI.Admin.Notification; +using Orchard.DisplayManagement.Shapes; namespace Orchard.OutputCache.Filters { public class OutputCacheFilter : FilterProvider, IActionFilter, IResultFilter { @@ -38,7 +40,6 @@ namespace Orchard.OutputCache.Filters { private readonly ISignals _signals; private readonly ShellSettings _shellSettings; private readonly ICacheControlStrategy _cacheControlStrategy; - private readonly INotificationManager _notificationManager; TextWriter _originalWriter; StringWriter _cachingWriter; @@ -57,9 +58,8 @@ namespace Orchard.OutputCache.Filters { ICacheService cacheService, ISignals signals, ShellSettings shellSettings, - ICacheControlStrategy cacheControlStrategy, - INotificationManager notificationManager - ) { + ICacheControlStrategy cacheControlStrategy) { + _cacheManager = cacheManager; _cacheStorageProvider = cacheStorageProvider; _tagCache = tagCache; @@ -71,7 +71,6 @@ namespace Orchard.OutputCache.Filters { _signals = signals; _shellSettings = shellSettings; _cacheControlStrategy = cacheControlStrategy; - _notificationManager = notificationManager; Logger = NullLogger.Instance; } @@ -228,7 +227,8 @@ namespace Orchard.OutputCache.Filters { var parameters = new Dictionary(filterContext.ActionParameters); foreach (var key in queryString.AllKeys) { - if (key == null) continue; + if (key == null || (_varyQueryStringParameters != null + && !_varyQueryStringParameters.Contains(key))) continue; // ignore pages with the RefreshKey if (String.Equals(RefreshKey, key, StringComparison.OrdinalIgnoreCase)) { @@ -351,7 +351,9 @@ namespace Orchard.OutputCache.Filters { } // don't cache the result if there were some notifications - if (_notificationManager.GetNotifications().Any()) { + var hasNotifications = !String.IsNullOrEmpty(Convert.ToString(filterContext.Controller.TempData["messages"])); + if (hasNotifications) { + Logger.Debug("Not caching: notifications present"); return; } @@ -379,10 +381,8 @@ namespace Orchard.OutputCache.Filters { Logger.Debug("Cache item added: " + _cacheItem.CacheKey); - // remove only the current version of the page - _cacheService.RemoveByTag(_cacheKey); - - // add data to cache + // update the cached data + _cacheStorageProvider.Remove(_cacheKey); _cacheStorageProvider.Set(_cacheKey, _cacheItem); // add to the tags index @@ -424,26 +424,23 @@ namespace Orchard.OutputCache.Filters { Logger.Debug("Redirect on POST"); var redirectUrl = redirectResult.Url; - if (!VirtualPathUtility.IsAbsolute(redirectUrl)) { - var applicationRoot = new UrlHelper(filterContext.HttpContext.Request.RequestContext).MakeAbsolute("/"); - if (redirectUrl.StartsWith(applicationRoot, StringComparison.OrdinalIgnoreCase)) { - redirectUrl = "~/" + redirectUrl.Substring(applicationRoot.Length); - redirectUrl = VirtualPathUtility.ToAbsolute(redirectUrl); - } + if (filterContext.HttpContext.Request.IsLocalUrl(redirectUrl)) { + var helper = new UrlHelper(filterContext.HttpContext.Request.RequestContext); + var absolutePath = new Uri(helper.MakeAbsolute(redirectUrl)).AbsolutePath; + + // querystring invariant key + var invariantCacheKey = ComputeCacheKey( + _shellSettings.Name, + absolutePath, + () => _workContext.CurrentCulture, + _themeManager.GetRequestTheme(filterContext.RequestContext).Id, + null + ); + + // remove all cached version of the same page + _cacheService.RemoveByTag(invariantCacheKey); } - // querystring invariant key - var invariantCacheKey = ComputeCacheKey( - _shellSettings.Name, - redirectUrl, - () => _workContext.CurrentCulture, - _themeManager.GetRequestTheme(filterContext.RequestContext).Id, - null - ); - - // remove all cached version of the same page - _cacheService.RemoveByTag(invariantCacheKey); - // adding a refresh key so that the redirection doesn't get restored // from a cached version on a proxy // this can happen when using public caching, we want to force the @@ -495,7 +492,6 @@ namespace Orchard.OutputCache.Filters { response.Cache.SetMaxAge(maxAge); } - response.Cache.VaryByParams["*"] = true; response.DisableUserCache(); // keeping this examples for later usage @@ -510,7 +506,10 @@ namespace Orchard.OutputCache.Filters { } } - if (_varyQueryStringParameters != null) { + if (_varyQueryStringParameters == null) { + response.Cache.VaryByParams["*"] = true; + } + else { foreach (var queryStringParam in _varyQueryStringParameters) { response.Cache.VaryByParams[queryStringParam] = true; } @@ -522,14 +521,7 @@ namespace Orchard.OutputCache.Filters { } private string ComputeCacheKey(ControllerContext controllerContext, IEnumerable> parameters) { - var url = controllerContext.HttpContext.Request.RawUrl; - if (!VirtualPathUtility.IsAbsolute(url)) { - var applicationRoot = new UrlHelper(controllerContext.HttpContext.Request.RequestContext).MakeAbsolute("/"); - if (url.StartsWith(applicationRoot, StringComparison.OrdinalIgnoreCase)) { - url = "~/" + url.Substring(applicationRoot.Length); - url = VirtualPathUtility.ToAbsolute(url); - } - } + var url = controllerContext.HttpContext.Request.Url.AbsolutePath; return ComputeCacheKey(_shellSettings.Name, url, () => _workContext.CurrentCulture, _themeManager.GetRequestTheme(controllerContext.RequestContext).Id, parameters); } diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Services/CacheService.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Services/CacheService.cs index 2be361bf9..493616818 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Services/CacheService.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Services/CacheService.cs @@ -40,6 +40,9 @@ namespace Orchard.OutputCache.Services { foreach(var key in _tagCache.GetTaggedItems(tag)) { _cacheStorageProvider.Remove(key); } + + // we no longer need the tag entry as the items have been removed + _tagCache.RemoveTag(tag); } public IEnumerable GetCacheItems() { diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Services/DefaultTagCache.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Services/DefaultTagCache.cs index 45a4a9d71..49d44216a 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Services/DefaultTagCache.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Services/DefaultTagCache.cs @@ -37,5 +37,10 @@ namespace Orchard.OutputCache.Services { return Enumerable.Empty(); } + + public void RemoveTag(string tag) { + HashSet set; + _dictionary.TryRemove(tag, out set); + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Services/ITagCache.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Services/ITagCache.cs index a0fcc46d0..1ad9de378 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Services/ITagCache.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Services/ITagCache.cs @@ -4,5 +4,6 @@ namespace Orchard.OutputCache.Services { public interface ITagCache : ISingletonDependency { void Tag(string tag, params string[] keys); IEnumerable GetTaggedItems(string tag); + void RemoveTag(string tag); } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Views/Statistics/Index.cshtml b/src/Orchard.Web/Modules/Orchard.OutputCache/Views/Statistics/Index.cshtml index 8c3329281..548d763dc 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Views/Statistics/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Views/Statistics/Index.cshtml @@ -15,6 +15,7 @@ @T("Url") + @T("Cache Key") @T("Cached On") @T("Cached Until")   @@ -23,6 +24,7 @@ @foreach (var cacheItem in Model.CacheItems) { @cacheItem.Url + @cacheItem.CacheKey @Display.DateTimeRelative(DateTimeUtc: cacheItem.CachedOnUtc) @cacheItem.ValidUntilUtc.ToLocalTime() @Html.ActionLink(T("Evict").Text, "Evict", new { Area = "Orchard.OutputCache", Controller = "Statistics", cacheKey = cacheItem.CacheKey }) diff --git a/src/Orchard.Web/Modules/Orchard.Projections/StandardQueries/QueryFeedQuery.cs b/src/Orchard.Web/Modules/Orchard.Projections/StandardQueries/QueryFeedQuery.cs index 2faaae7a9..f3a62c87e 100644 --- a/src/Orchard.Web/Modules/Orchard.Projections/StandardQueries/QueryFeedQuery.cs +++ b/src/Orchard.Web/Modules/Orchard.Projections/StandardQueries/QueryFeedQuery.cs @@ -39,7 +39,7 @@ namespace Orchard.Projections.StandardQueries { public void Execute(FeedContext context) { var projectionId = context.ValueProvider.GetValue("projection"); - if (projectionId == null) + if (projectionId == null || String.IsNullOrEmpty(projectionId.AttemptedValue)) return; var limitValue = context.ValueProvider.GetValue("limit"); diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs b/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs index a93ae29ea..9579ffadc 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs +++ b/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs @@ -38,8 +38,9 @@ namespace Orchard.Templates.Services { BindingName = "Templates", Binding = ctx => CoerceHtmlString(_templateService.Execute( templateResult.Template, - templateResult.Name, - templateResult.Processor, ctx.Value)) + templateResult.Name, + templateResult.Processor, ctx.Value)), + ShapeDescriptor = new ShapeDescriptor { ShapeType = shapeType } }; return true; diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Providers/RssPartFeedItemBuilder.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Providers/RssPartFeedItemBuilder.cs index 0892c5a88..f7bbf5ecb 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Providers/RssPartFeedItemBuilder.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Providers/RssPartFeedItemBuilder.cs @@ -85,7 +85,7 @@ namespace Orchard.Tokens.Providers { FeedItem item = feedItem; context.Response.Contextualize(requestContext => { - description.Value = _tokenizer.Replace(settings.Description, new { Content = item.Item, Text = description.Value }); + description.Value = _tokenizer.Replace(settings.Description, new { Content = item.Item, Text = description.Value }, new ReplaceOptions { Encoding = ReplaceOptions.NoEncode }); }); } } diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Views/DefinitionTemplates/RssPartSettings.cshtml b/src/Orchard.Web/Modules/Orchard.Tokens/Views/DefinitionTemplates/RssPartSettings.cshtml index a3267ff01..9beb00838 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Views/DefinitionTemplates/RssPartSettings.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Views/DefinitionTemplates/RssPartSettings.cshtml @@ -15,7 +15,7 @@
@Html.TextBoxFor(m => m.Description, new { @class = "tokenized text medium" }) - @T("The description field of the RSS item") + @T("The description field of the RSS item. The content needs to be raw HTML, i.e. not encoded.")
diff --git a/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs b/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs index 35699d7da..6360a2574 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs +++ b/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs @@ -64,9 +64,9 @@ namespace Orchard.Users.Controllers { } [AlwaysAccessible] - public ActionResult LogOn() { + public ActionResult LogOn(string returnUrl) { if (_authenticationService.GetAuthenticatedUser() != null) - return Redirect("~/"); + return this.RedirectLocal(returnUrl); var shape = _orchardServices.New.LogOn().Title(T("Log On").Text); return new ShapeResult(this, shape); diff --git a/src/Orchard/Data/Migration/DataMigrationManager.cs b/src/Orchard/Data/Migration/DataMigrationManager.cs index 2ce65beab..1ef6e33d7 100644 --- a/src/Orchard/Data/Migration/DataMigrationManager.cs +++ b/src/Orchard/Data/Migration/DataMigrationManager.cs @@ -22,7 +22,7 @@ namespace Orchard.Data.Migration { private readonly IContentDefinitionManager _contentDefinitionManager; private readonly ITransactionManager _transactionManager; - private List _processedFeatures; + private readonly List _processedFeatures; public DataMigrationManager( IEnumerable dataMigrations, @@ -40,6 +40,7 @@ namespace Orchard.Data.Migration { _processedFeatures = new List(); Logger = NullLogger.Instance; + T = NullLocalizer.Instance; } public Localizer T { get; set; } public ILogger Logger { get; set; } @@ -118,11 +119,11 @@ namespace Orchard.Data.Migration { while (lookupTable.ContainsKey(current)) { try { - Logger.Information("Applying migration for {0} from version {1}", feature, current); + Logger.Information("Applying migration for {0} from version {1}.", feature, current); current = (int)lookupTable[current].Invoke(migration, new object[0]); } catch (Exception ex) { - Logger.Error(ex, "An unexpected error occurred while applying migration on {0} from version {1}", feature, current); + Logger.Error(ex, "An unexpected error occurred while applying migration on {0} from version {1}.", feature, current); throw; } } @@ -139,15 +140,16 @@ namespace Orchard.Data.Migration { } } catch (Exception e) { - Logger.Error(e, "Error while running migration version {0} for {1}", current, feature); + Logger.Error(e, "Error while running migration version {0} for {1}.", current, feature); _transactionManager.Cancel(); + throw new OrchardException(T("Error while running migration version {0} for {1}.", current, feature), e); } } } public void Uninstall(string feature) { - Logger.Information("Uninstalling feature: {0}", feature); + Logger.Information("Uninstalling feature: {0}.", feature); var migrations = GetDataMigrations(feature); diff --git a/src/Orchard/Data/Repository.cs b/src/Orchard/Data/Repository.cs index 4f42f512a..92bb29101 100644 --- a/src/Orchard/Data/Repository.cs +++ b/src/Orchard/Data/Repository.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; @@ -111,6 +112,30 @@ namespace Orchard.Data { Logger.Debug("Copy {0} {1}", source, target); var metadata = Session.SessionFactory.GetClassMetadata(typeof (T)); var values = metadata.GetPropertyValues(source, EntityMode.Poco); + + //This method is currently only used by StorageVersionFilter<>.Versioning() + //In order to prevent shared references to the same collection instance + //Instances of IList<> need to be copied to a new collection instance + for (var index = 0; index < values.Length; index++) { + var value = values[index]; + if (value == null) + continue; + + var type = value.GetType(); + var isGenericList = type.GetInterfaces() + .Where(i => i.IsGenericType) + .Any(i => i.GetGenericTypeDefinition() == typeof(IList<>)); + + if(!isGenericList) + continue; + + var genericArgument = type.GetGenericArguments().First(); + var genericType = typeof(List<>).MakeGenericType(new[] { genericArgument }); + + var listValues = ((IList)value); + values[index] = Activator.CreateInstance(genericType, new[] { listValues }); + } + metadata.SetPropertyValues(target, values, EntityMode.Poco); } diff --git a/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/PlacementFileParser.cs b/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/PlacementFileParser.cs index 4b736d874..8725ded54 100644 --- a/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/PlacementFileParser.cs +++ b/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/PlacementFileParser.cs @@ -12,6 +12,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapePlacementStrategy { /// public interface IPlacementFileParser : IDependency { PlacementFile Parse(string virtualPath); + PlacementFile ParseText(string placementText); } @@ -37,11 +38,11 @@ namespace Orchard.DisplayManagement.Descriptors.ShapePlacementStrategy { } var placementText = _webSiteFolder.ReadFile(virtualPath); - return ParseImplementation(virtualPath, placementText); + return ParseText(placementText); }); } - private PlacementFile ParseImplementation(string virtualPath, string placementText) { + public PlacementFile ParseText(string placementText) { if (placementText == null) return null;