mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Merge remote-tracking branch 'origin/dev' into feature/tenantstateinitializing
This commit is contained in:
@@ -13,7 +13,8 @@ var glob = require("glob"),
|
|||||||
uglify = require("gulp-uglify"),
|
uglify = require("gulp-uglify"),
|
||||||
rename = require("gulp-rename"),
|
rename = require("gulp-rename"),
|
||||||
concat = require("gulp-concat"),
|
concat = require("gulp-concat"),
|
||||||
header = require("gulp-header");
|
header = require("gulp-header"),
|
||||||
|
fs = require("fs");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** GULP TASKS
|
** GULP TASKS
|
||||||
@@ -37,32 +38,53 @@ gulp.task("rebuild", function () {
|
|||||||
return merge(assetGroupTasks);
|
return merge(assetGroupTasks);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Continuous watch (each asset group is built whenever one of its inputs changes).
|
|
||||||
|
// Set "Watchers" as sub-processes in order to restart the task when Assets.json changes.
|
||||||
gulp.task("watch", function () {
|
gulp.task("watch", function () {
|
||||||
var pathWin32 = require("path");
|
var watchers;
|
||||||
getAssetGroups().forEach(function (assetGroup) {
|
function restart() {
|
||||||
var watchPaths = assetGroup.inputPaths.concat(assetGroup.watchPaths);
|
if (watchers) {
|
||||||
gulp.watch(watchPaths, function (event) {
|
watchers.forEach(function (w) {
|
||||||
var isConcat = path.basename(assetGroup.outputFileName, path.extname(assetGroup.outputFileName)) !== "@";
|
w.remove();
|
||||||
if (isConcat)
|
w.end();
|
||||||
console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group with output '" + assetGroup.outputPath + "'.");
|
});
|
||||||
else
|
}
|
||||||
console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group.");
|
watchers = [];
|
||||||
var doRebuild = true;
|
// Continuous watch (each asset group is built whenever one of its inputs changes).
|
||||||
var task = createAssetGroupTask(assetGroup, doRebuild);
|
getAssetGroups().forEach(function (assetGroup) {
|
||||||
|
var watchPaths = assetGroup.inputPaths.concat(assetGroup.watchPaths);
|
||||||
|
var watcher = gulp.watch(watchPaths, function (event) {
|
||||||
|
var isConcat = path.basename(assetGroup.outputFileName, path.extname(assetGroup.outputFileName)) !== "@";
|
||||||
|
if (isConcat)
|
||||||
|
console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group with output '" + assetGroup.outputPath + "'.");
|
||||||
|
else
|
||||||
|
console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group.");
|
||||||
|
var doRebuild = true;
|
||||||
|
var task = createAssetGroupTask(assetGroup, doRebuild);
|
||||||
|
});
|
||||||
|
watchers.push(watcher);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
var p;
|
||||||
|
if (p) { p.exit(); }
|
||||||
|
p = gulp.watch("Orchard.Web/{Core,Modules,Themes}/*/Assets.json", function (event) {
|
||||||
|
console.log("Asset file '" + event.path + "' was " + event.type + ", resetting asset watchers.");
|
||||||
|
restart();
|
||||||
});
|
});
|
||||||
|
restart();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** ASSET GROUPS
|
** ASSET GROUPS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function getAssetGroups() {
|
function getAssetGroups() {
|
||||||
var assetManifestPaths = glob.sync("Orchard.Web/{Core,Modules,Themes}/*/Assets.json");
|
var assetManifestPaths = glob.sync("Orchard.Web/{Core,Modules,Themes}/*/Assets.json", {});
|
||||||
var assetGroups = [];
|
var assetGroups = [];
|
||||||
assetManifestPaths.forEach(function (assetManifestPath) {
|
assetManifestPaths.forEach(function (assetManifestPath) {
|
||||||
var assetManifest = require("./" + assetManifestPath);
|
var file = './' + assetManifestPath;
|
||||||
|
var json = fs.readFileSync(file, 'utf8');
|
||||||
|
assetManifest = eval(json);
|
||||||
assetManifest.forEach(function (assetGroup) {
|
assetManifest.forEach(function (assetGroup) {
|
||||||
resolveAssetGroupPaths(assetGroup, assetManifestPath);
|
resolveAssetGroupPaths(assetGroup, assetManifestPath);
|
||||||
assetGroups.push(assetGroup);
|
assetGroups.push(assetGroup);
|
||||||
|
@@ -110,23 +110,23 @@ namespace Orchard.Tests.Modules.Recipes.Services {
|
|||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void HarvestRecipesFailsToFindRecipesWhenCalledWithNotExistingExtension() {
|
public void HarvestRecipesFailsToFindRecipesWhenCalledWithNotExistingExtension() {
|
||||||
var recipes = (List<Recipe>)_recipeHarvester.HarvestRecipes("cantfindme");
|
var recipes = _recipeHarvester.HarvestRecipes("cantfindme");
|
||||||
|
|
||||||
Assert.That(recipes.Count, Is.EqualTo(0));
|
Assert.That(recipes.Count(), Is.EqualTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void HarvestRecipesShouldHarvestRecipeXmlFiles() {
|
public void HarvestRecipesShouldHarvestRecipeXmlFiles() {
|
||||||
var recipes = (List<Recipe>)_recipeHarvester.HarvestRecipes("Sample1");
|
var recipes = _recipeHarvester.HarvestRecipes("Sample1");
|
||||||
Assert.That(recipes.Count, Is.EqualTo(1));
|
Assert.That(recipes.Count(), Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ParseRecipeLoadsRecipeMetaDataIntoModel() {
|
public void ParseRecipeLoadsRecipeMetaDataIntoModel() {
|
||||||
var recipes = (List<Recipe>)_recipeHarvester.HarvestRecipes("Sample1");
|
var recipes = _recipeHarvester.HarvestRecipes("Sample1");
|
||||||
Assert.That(recipes.Count, Is.EqualTo(1));
|
Assert.That(recipes.Count(), Is.EqualTo(1));
|
||||||
|
|
||||||
var sampleRecipe = recipes[0];
|
var sampleRecipe = recipes.First();
|
||||||
Assert.That(sampleRecipe.Name, Is.EqualTo("cms"));
|
Assert.That(sampleRecipe.Name, Is.EqualTo("cms"));
|
||||||
Assert.That(sampleRecipe.Description, Is.EqualTo("a sample Orchard recipe describing a cms"));
|
Assert.That(sampleRecipe.Description, Is.EqualTo("a sample Orchard recipe describing a cms"));
|
||||||
Assert.That(sampleRecipe.Author, Is.EqualTo("orchard"));
|
Assert.That(sampleRecipe.Author, Is.EqualTo("orchard"));
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
using Autofac;
|
using Autofac;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using Orchard.Caching;
|
using Orchard.Caching;
|
||||||
@@ -78,6 +80,42 @@ namespace Orchard.Tests.Caching {
|
|||||||
Is.Not.SameAs(c2.CacheManager.GetCache<string, string>()));
|
Is.Not.SameAs(c2.CacheManager.GetCache<string, string>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CacheManagerIsNotBlocking() {
|
||||||
|
var hits = 0;
|
||||||
|
string result = "";
|
||||||
|
|
||||||
|
Enumerable.Range(0, 5).AsParallel().ForAll(x =>
|
||||||
|
result = _cacheManager.Get("testItem", ctx => {
|
||||||
|
// by waiting for 100ms we expect all the calls to Get
|
||||||
|
// to enter this lambda
|
||||||
|
Thread.Sleep(100);
|
||||||
|
hits++;
|
||||||
|
return "testResult";
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo("testResult"));
|
||||||
|
Assert.That(hits, Is.GreaterThan(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CacheManagerIsBlocking() {
|
||||||
|
var hits = 0;
|
||||||
|
string result = "";
|
||||||
|
|
||||||
|
Enumerable.Range(0, 5).AsParallel().ForAll(x =>
|
||||||
|
result = _cacheManager.Get("testItem", true, ctx => {
|
||||||
|
Thread.Sleep(100);
|
||||||
|
hits++;
|
||||||
|
return "testResult";
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo("testResult"));
|
||||||
|
Assert.That(hits, Is.EqualTo(1));
|
||||||
|
}
|
||||||
|
|
||||||
class ComponentOne {
|
class ComponentOne {
|
||||||
public ICacheManager CacheManager { get; set; }
|
public ICacheManager CacheManager { get; set; }
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@ using Orchard.Localization.Models;
|
|||||||
|
|
||||||
namespace Orchard.Tests.Localization {
|
namespace Orchard.Tests.Localization {
|
||||||
|
|
||||||
[TestFixture]
|
[TestFixture()]
|
||||||
public class DateTimePartsTests {
|
public class DateTimePartsTests {
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -13,7 +12,8 @@ using Orchard.Localization.Services;
|
|||||||
|
|
||||||
namespace Orchard.Tests.Localization {
|
namespace Orchard.Tests.Localization {
|
||||||
|
|
||||||
[TestFixture]
|
[TestFixture()]
|
||||||
|
[Category("longrunning")]
|
||||||
public class DefaultDateFormatterTests {
|
public class DefaultDateFormatterTests {
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
|
@@ -9,7 +9,7 @@ namespace Orchard.Tests.Stubs {
|
|||||||
WorkContext = workContext;
|
WorkContext = workContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorkContext WorkContext { get; }
|
public WorkContext WorkContext { get; private set; }
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
_lifetimeScope.Dispose();
|
_lifetimeScope.Dispose();
|
||||||
|
@@ -89,9 +89,9 @@ namespace Orchard.WarmupStarter {
|
|||||||
var result = _initialization(application);
|
var result = _initialization(application);
|
||||||
_initializationResult = result;
|
_initializationResult = result;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
lock (_synLock) {
|
lock (_synLock) {
|
||||||
_error = e;
|
_error = ex;
|
||||||
_previousError = null;
|
_previousError = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,6 +17,7 @@ using Orchard.UI.Navigation;
|
|||||||
using Orchard.Utility;
|
using Orchard.Utility;
|
||||||
using System;
|
using System;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Core.Navigation.Controllers {
|
namespace Orchard.Core.Navigation.Controllers {
|
||||||
[ValidateInput(false)]
|
[ValidateInput(false)]
|
||||||
@@ -179,6 +180,10 @@ namespace Orchard.Core.Navigation.Controllers {
|
|||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
catch (Exception exception) {
|
catch (Exception exception) {
|
||||||
|
if (exception.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
Logger.Error(T("Creating menu item failed: {0}", exception.Message).Text);
|
Logger.Error(T("Creating menu item failed: {0}", exception.Message).Text);
|
||||||
Services.Notifier.Error(T("Creating menu item failed: {0}", exception.Message));
|
Services.Notifier.Error(T("Creating menu item failed: {0}", exception.Message));
|
||||||
return this.RedirectLocal(returnUrl, () => RedirectToAction("Index"));
|
return this.RedirectLocal(returnUrl, () => RedirectToAction("Index"));
|
||||||
|
@@ -11,6 +11,7 @@ using Orchard.Security.Permissions;
|
|||||||
using Orchard.UI;
|
using Orchard.UI;
|
||||||
using Orchard.UI.Navigation;
|
using Orchard.UI.Navigation;
|
||||||
using Orchard.Utility;
|
using Orchard.Utility;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Core.Navigation.Services {
|
namespace Orchard.Core.Navigation.Services {
|
||||||
public class NavigationManager : INavigationManager {
|
public class NavigationManager : INavigationManager {
|
||||||
@@ -152,6 +153,9 @@ namespace Orchard.Core.Navigation.Services {
|
|||||||
items = builder.Build();
|
items = builder.Build();
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
Logger.Error(ex, "Unexpected error while querying a navigation provider. It was ignored. The menu provided by the provider may not be complete.");
|
Logger.Error(ex, "Unexpected error while querying a navigation provider. It was ignored. The menu provided by the provider may not be complete.");
|
||||||
}
|
}
|
||||||
if (items != null) {
|
if (items != null) {
|
||||||
@@ -170,6 +174,9 @@ namespace Orchard.Core.Navigation.Services {
|
|||||||
items = builder.Build();
|
items = builder.Build();
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
Logger.Error(ex, "Unexpected error while querying a menu provider. It was ignored. The menu provided by the provider may not be complete.");
|
Logger.Error(ex, "Unexpected error while querying a menu provider. It was ignored. The menu provided by the provider may not be complete.");
|
||||||
}
|
}
|
||||||
if (items != null) {
|
if (items != null) {
|
||||||
@@ -188,6 +195,9 @@ namespace Orchard.Core.Navigation.Services {
|
|||||||
imageSets = builder.BuildImageSets();
|
imageSets = builder.BuildImageSets();
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
Logger.Error(ex, "Unexpected error while querying a navigation provider. It was ignored. The menu provided by the provider may not be complete.");
|
Logger.Error(ex, "Unexpected error while querying a navigation provider. It was ignored. The menu provided by the provider may not be complete.");
|
||||||
}
|
}
|
||||||
if (imageSets != null) {
|
if (imageSets != null) {
|
||||||
|
@@ -8,6 +8,7 @@ using Orchard.Logging;
|
|||||||
using Orchard.Services;
|
using Orchard.Services;
|
||||||
using Orchard.Tasks;
|
using Orchard.Tasks;
|
||||||
using Orchard.Tasks.Scheduling;
|
using Orchard.Tasks.Scheduling;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Core.Scheduling.Services {
|
namespace Orchard.Core.Scheduling.Services {
|
||||||
public class ScheduledTaskExecutor : IBackgroundTask {
|
public class ScheduledTaskExecutor : IBackgroundTask {
|
||||||
@@ -63,6 +64,9 @@ namespace Orchard.Core.Scheduling.Services {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
Logger.Warning(ex, "Unable to process scheduled task #{0} of type {1}", taskEntry.Id, taskEntry.Action);
|
Logger.Warning(ex, "Unable to process scheduled task #{0} of type {1}", taskEntry.Id, taskEntry.Action);
|
||||||
_transactionManager.Cancel();
|
_transactionManager.Cancel();
|
||||||
}
|
}
|
||||||
|
@@ -10,6 +10,7 @@ using Orchard.Logging;
|
|||||||
using Orchard.Security;
|
using Orchard.Security;
|
||||||
using Orchard.Settings;
|
using Orchard.Settings;
|
||||||
using Orchard.UI.Notify;
|
using Orchard.UI.Notify;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Core.Settings.Drivers {
|
namespace Orchard.Core.Settings.Drivers {
|
||||||
public class SiteSettingsPartDriver : ContentPartDriver<SiteSettingsPart> {
|
public class SiteSettingsPartDriver : ContentPartDriver<SiteSettingsPart> {
|
||||||
@@ -100,9 +101,12 @@ namespace Orchard.Core.Settings.Drivers {
|
|||||||
using (request.GetResponse() as HttpWebResponse) {}
|
using (request.GetResponse() as HttpWebResponse) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
_notifier.Warning(T("The base url you entered could not be requested from current location."));
|
_notifier.Warning(T("The base url you entered could not be requested from current location."));
|
||||||
Logger.Warning(e, "Could not query base url: {0}", model.Site.BaseUrl);
|
Logger.Warning(ex, "Could not query base url: {0}", model.Site.BaseUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@ using Orchard.ContentManagement.MetaData.Services;
|
|||||||
using Orchard.Core.Settings.Metadata.Records;
|
using Orchard.Core.Settings.Metadata.Records;
|
||||||
using Orchard.Data;
|
using Orchard.Data;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Core.Settings.Metadata {
|
namespace Orchard.Core.Settings.Metadata {
|
||||||
public class ContentDefinitionManager : Component, IContentDefinitionManager {
|
public class ContentDefinitionManager : Component, IContentDefinitionManager {
|
||||||
@@ -124,7 +125,7 @@ namespace Orchard.Core.Settings.Metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private IDictionary<string, ContentTypeDefinition> AcquireContentTypeDefinitions() {
|
private IDictionary<string, ContentTypeDefinition> AcquireContentTypeDefinitions() {
|
||||||
return _cacheManager.Get("ContentTypeDefinitions", ctx => {
|
return _cacheManager.Get("ContentTypeDefinitions", true, ctx => {
|
||||||
MonitorContentDefinitionSignal(ctx);
|
MonitorContentDefinitionSignal(ctx);
|
||||||
|
|
||||||
AcquireContentPartDefinitions();
|
AcquireContentPartDefinitions();
|
||||||
@@ -139,7 +140,7 @@ namespace Orchard.Core.Settings.Metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private IDictionary<string, ContentPartDefinition> AcquireContentPartDefinitions() {
|
private IDictionary<string, ContentPartDefinition> AcquireContentPartDefinitions() {
|
||||||
return _cacheManager.Get("ContentPartDefinitions", ctx => {
|
return _cacheManager.Get("ContentPartDefinitions", true, ctx => {
|
||||||
MonitorContentDefinitionSignal(ctx);
|
MonitorContentDefinitionSignal(ctx);
|
||||||
|
|
||||||
var contentPartDefinitionRecords = _partDefinitionRepository.Table
|
var contentPartDefinitionRecords = _partDefinitionRepository.Table
|
||||||
@@ -152,7 +153,7 @@ namespace Orchard.Core.Settings.Metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private IDictionary<string, ContentFieldDefinition> AcquireContentFieldDefinitions() {
|
private IDictionary<string, ContentFieldDefinition> AcquireContentFieldDefinitions() {
|
||||||
return _cacheManager.Get("ContentFieldDefinitions", ctx => {
|
return _cacheManager.Get("ContentFieldDefinitions", true, ctx => {
|
||||||
MonitorContentDefinitionSignal(ctx);
|
MonitorContentDefinitionSignal(ctx);
|
||||||
|
|
||||||
return _fieldDefinitionRepository.Table.Select(Build).ToDictionary(x => x.Name, y => y);
|
return _fieldDefinitionRepository.Table.Select(Build).ToDictionary(x => x.Name, y => y);
|
||||||
@@ -282,6 +283,9 @@ namespace Orchard.Core.Settings.Metadata {
|
|||||||
return XElement.Parse(settings);
|
return XElement.Parse(settings);
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
Logger.Error(ex, "Unable to parse settings xml");
|
Logger.Error(ex, "Unable to parse settings xml");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@ namespace Orchard.Core.Settings.Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ISite GetSiteSettings() {
|
public ISite GetSiteSettings() {
|
||||||
var siteId = _cacheManager.Get("SiteId", ctx => {
|
var siteId = _cacheManager.Get("SiteId", true, ctx => {
|
||||||
var site = _contentManager.Query("Site")
|
var site = _contentManager.Query("Site")
|
||||||
.List()
|
.List()
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
using Orchard.DisplayManagement;
|
using Orchard.DisplayManagement;
|
||||||
@@ -32,8 +31,20 @@ namespace Orchard.Core.Shapes {
|
|||||||
DateTimeUtc = DateTimeUtc != System.DateTime.MinValue ? DateTimeUtc : dateTimeUtc; // Both capitalizations retained for compatibility.
|
DateTimeUtc = DateTimeUtc != System.DateTime.MinValue ? DateTimeUtc : dateTimeUtc; // Both capitalizations retained for compatibility.
|
||||||
var time = _clock.UtcNow - DateTimeUtc;
|
var time = _clock.UtcNow - DateTimeUtc;
|
||||||
|
|
||||||
if (time.TotalDays > 7 || time.TotalDays < -7)
|
if (time.TotalYears() > 1)
|
||||||
return Display.DateTime(DateTimeUtc: DateTimeUtc, CustomFormat: null);
|
return T.Plural("1 year ago", "{0} years ago", time.TotalYears());
|
||||||
|
if (time.TotalYears() < -1)
|
||||||
|
return T.Plural("in 1 year", "in {0} years", -time.TotalYears());
|
||||||
|
|
||||||
|
if (time.TotalMonths() > 1)
|
||||||
|
return T.Plural("1 month ago", "{0} months ago", time.TotalMonths());
|
||||||
|
if (time.TotalMonths() < -1)
|
||||||
|
return T.Plural("in 1 month", "in {0} months", -time.TotalMonths());
|
||||||
|
|
||||||
|
if (time.TotalWeeks() > 1)
|
||||||
|
return T.Plural("1 week ago", "{0} weeks ago", time.TotalWeeks());
|
||||||
|
if (time.TotalWeeks() < -1)
|
||||||
|
return T.Plural("in 1 week", "in {0} weeks", -time.TotalWeeks());
|
||||||
|
|
||||||
if (time.TotalHours > 24)
|
if (time.TotalHours > 24)
|
||||||
return T.Plural("1 day ago", "{0} days ago", time.Days);
|
return T.Plural("1 day ago", "{0} days ago", time.Days);
|
||||||
@@ -71,4 +82,18 @@ namespace Orchard.Core.Shapes {
|
|||||||
return new MvcHtmlString(_dateLocalizationServices.ConvertToLocalizedString(DateTimeUtc, CustomFormat.Text));
|
return new MvcHtmlString(_dateLocalizationServices.ConvertToLocalizedString(DateTimeUtc, CustomFormat.Text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public static class TimespanExtensions {
|
||||||
|
public static int TotalWeeks(this TimeSpan time) {
|
||||||
|
return (int)time.TotalDays / 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int TotalMonths(this TimeSpan time) {
|
||||||
|
return (int)time.TotalDays / 31;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int TotalYears(this TimeSpan time) {
|
||||||
|
return (int)time.TotalDays / 365;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -17,7 +17,7 @@ namespace Orchard.ContentPicker.Fields {
|
|||||||
|
|
||||||
public IEnumerable<ContentItem> ContentItems {
|
public IEnumerable<ContentItem> ContentItems {
|
||||||
get {
|
get {
|
||||||
return _contentItems.Value;
|
return _contentItems.Value ?? Enumerable.Empty<ContentItem>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@ namespace Orchard.ContentTypes.Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<StereotypeDescription> GetStereotypes() {
|
public IEnumerable<StereotypeDescription> GetStereotypes() {
|
||||||
return _cacheManager.Get("ContentType.Stereotypes", context => {
|
return _cacheManager.Get("ContentType.Stereotypes", true, context => {
|
||||||
|
|
||||||
// TODO: Implement a signal in ContentDefinitionManager that gets raised whenever a type definition is updated.
|
// TODO: Implement a signal in ContentDefinitionManager that gets raised whenever a type definition is updated.
|
||||||
// For now, we'll just cache the stereotypes for 1 minute.
|
// For now, we'll just cache the stereotypes for 1 minute.
|
||||||
|
@@ -1,10 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Cryptography;
|
||||||
using Orchard.ContentManagement.MetaData;
|
using Orchard.ContentManagement.MetaData;
|
||||||
using Orchard.Core.Contents.Extensions;
|
using Orchard.Core.Contents.Extensions;
|
||||||
|
using Orchard.Data;
|
||||||
using Orchard.Data.Migration;
|
using Orchard.Data.Migration;
|
||||||
|
|
||||||
namespace Orchard.DynamicForms {
|
namespace Orchard.DynamicForms {
|
||||||
public class Migrations : DataMigrationImpl {
|
public class Migrations : DataMigrationImpl {
|
||||||
|
private readonly byte[] _oldLayoutHash = new byte[] { 0x91, 0x10, 0x3b, 0x97, 0xce, 0x1e, 0x1e, 0xc7, 0x7a, 0x41, 0xf7, 0x82, 0xe8, 0x58, 0x85, 0x91 };
|
||||||
|
|
||||||
private const string DefaultFormLayoutData =
|
private const string DefaultFormLayoutData =
|
||||||
@"{
|
@"{
|
||||||
""elements"": [
|
""elements"": [
|
||||||
@@ -59,7 +64,52 @@ namespace Orchard.DynamicForms {
|
|||||||
.WithSetting("LayoutTypePartSettings.DefaultLayoutData", DefaultFormLayoutData))
|
.WithSetting("LayoutTypePartSettings.DefaultLayoutData", DefaultFormLayoutData))
|
||||||
.WithSetting("Stereotype", "Widget")
|
.WithSetting("Stereotype", "Widget")
|
||||||
.DisplayedAs("Form Widget"));
|
.DisplayedAs("Form Widget"));
|
||||||
return 1;
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int UpdateFrom1() {
|
||||||
|
// if the default layout data was unchanged, fix it with the new default
|
||||||
|
|
||||||
|
var formLayoutPart = ContentDefinitionManager
|
||||||
|
.GetTypeDefinition("Form")
|
||||||
|
.Parts
|
||||||
|
.FirstOrDefault(x => x.PartDefinition.Name == "LayoutPart");
|
||||||
|
|
||||||
|
if (formLayoutPart != null &&
|
||||||
|
formLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"] != null) {
|
||||||
|
var layout = formLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"];
|
||||||
|
|
||||||
|
if(GetMD5(layout) == _oldLayoutHash) {
|
||||||
|
ContentDefinitionManager.AlterTypeDefinition("Form", type => type
|
||||||
|
.WithPart("LayoutPart", p => p
|
||||||
|
.WithSetting("LayoutTypePartSettings.DefaultLayoutData", DefaultFormLayoutData))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var formWidgetLayoutPart = ContentDefinitionManager
|
||||||
|
.GetTypeDefinition("FormWidget")
|
||||||
|
.Parts
|
||||||
|
.FirstOrDefault(x => x.PartDefinition.Name == "LayoutPart");
|
||||||
|
|
||||||
|
if (formWidgetLayoutPart != null &&
|
||||||
|
formWidgetLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"] != null) {
|
||||||
|
var layout = formWidgetLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"];
|
||||||
|
|
||||||
|
if (GetMD5(layout) == _oldLayoutHash) {
|
||||||
|
ContentDefinitionManager.AlterTypeDefinition("FormWidget", type => type
|
||||||
|
.WithPart("LayoutPart", p => p
|
||||||
|
.WithSetting("LayoutTypePartSettings.DefaultLayoutData", DefaultFormLayoutData))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] GetMD5(string text) {
|
||||||
|
byte[] encodedText = System.Text.Encoding.UTF8.GetBytes(text);
|
||||||
|
return ((HashAlgorithm)CryptoConfig.CreateFromName("MD5")).ComputeHash(encodedText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
Name: Custom Forms
|
Name: Dynamic Forms
|
||||||
AntiForgery: enabled
|
AntiForgery: enabled
|
||||||
Author: The Orchard Team
|
Author: The Orchard Team
|
||||||
Website: http://orchardcustomforms.codeplex.com
|
Website: http://www.orchardproject.net/
|
||||||
Version: 1.9.1
|
Version: 1.9.1
|
||||||
OrchardVersion: 1.9
|
OrchardVersion: 1.9
|
||||||
Description: Create custom forms like contact forms using layouts.
|
Description: Create custom forms like contact forms using layouts.
|
||||||
|
@@ -7,7 +7,7 @@ namespace Orchard.DynamicForms.Tokens {
|
|||||||
|
|
||||||
public void Describe(DescribeContext context) {
|
public void Describe(DescribeContext context) {
|
||||||
context.For("FormSubmission", T("Dynamic Form submission"), T("Dynamic Form Submission tokens for use in workflows handling the Dynamic Form Submitted event."))
|
context.For("FormSubmission", T("Dynamic Form submission"), T("Dynamic Form Submission tokens for use in workflows handling the Dynamic Form Submitted event."))
|
||||||
.Token("Field:*", T("Field:<field name>"), T("The posted field value to access."))
|
.Token("Field:*", T("Field:<field name>"), T("The posted field value to access."), "Text")
|
||||||
.Token("IsValid:*", T("IsValid:<field name>"), T("The posted field validation status."))
|
.Token("IsValid:*", T("IsValid:<field name>"), T("The posted field validation status."))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
@@ -15,10 +15,20 @@ namespace Orchard.DynamicForms.Tokens {
|
|||||||
public void Evaluate(EvaluateContext context) {
|
public void Evaluate(EvaluateContext context) {
|
||||||
context.For<FormSubmissionTokenContext>("FormSubmission")
|
context.For<FormSubmissionTokenContext>("FormSubmission")
|
||||||
.Token(token => token.StartsWith("Field:", StringComparison.OrdinalIgnoreCase) ? token.Substring("Field:".Length) : null, GetFieldValue)
|
.Token(token => token.StartsWith("Field:", StringComparison.OrdinalIgnoreCase) ? token.Substring("Field:".Length) : null, GetFieldValue)
|
||||||
|
.Chain(FilterChainParam, "Text", GetFieldValue)
|
||||||
.Token(token => token.StartsWith("IsValid:", StringComparison.OrdinalIgnoreCase) ? token.Substring("IsValid:".Length) : null, GetFieldValidationStatus);
|
.Token(token => token.StartsWith("IsValid:", StringComparison.OrdinalIgnoreCase) ? token.Substring("IsValid:".Length) : null, GetFieldValidationStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
private object GetFieldValue(string fieldName, FormSubmissionTokenContext context) {
|
private static Tuple<string, string> FilterChainParam(string token) {
|
||||||
|
int tokenLength = "Field:".Length;
|
||||||
|
int chainIndex = token.IndexOf('.');
|
||||||
|
if (token.StartsWith("Field:", StringComparison.OrdinalIgnoreCase) && chainIndex > tokenLength)
|
||||||
|
return new Tuple<string, string>(token.Substring(tokenLength, chainIndex - tokenLength), token.Substring(chainIndex + 1));
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetFieldValue(string fieldName, FormSubmissionTokenContext context) {
|
||||||
return context.PostedValues[fieldName];
|
return context.PostedValues[fieldName];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -307,10 +307,9 @@ namespace Orchard.Layouts.Drivers {
|
|||||||
|
|
||||||
var queryPart = query.As<QueryPart>();
|
var queryPart = query.As<QueryPart>();
|
||||||
var layoutIndex = XmlHelper.Parse<int>(context.ExportableData.Get("LayoutIndex"));
|
var layoutIndex = XmlHelper.Parse<int>(context.ExportableData.Get("LayoutIndex"));
|
||||||
var layout = queryPart.Layouts[layoutIndex];
|
|
||||||
|
|
||||||
element.QueryId = queryPart.Id;
|
element.QueryId = queryPart.Id;
|
||||||
element.LayoutId = layout.Id;
|
element.LayoutId = layoutIndex != -1 ? queryPart.Layouts[layoutIndex].Id : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetLayoutDescription(IEnumerable<LayoutDescriptor> layouts, LayoutRecord l) {
|
private static string GetLayoutDescription(IEnumerable<LayoutDescriptor> layouts, LayoutRecord l) {
|
||||||
|
@@ -38,7 +38,7 @@ namespace Orchard.Layouts.Services {
|
|||||||
public IEnumerable<ElementDescriptor> DescribeElements(DescribeElementsContext context) {
|
public IEnumerable<ElementDescriptor> DescribeElements(DescribeElementsContext context) {
|
||||||
var contentType = context.Content != null ? context.Content.ContentItem.ContentType : default(string);
|
var contentType = context.Content != null ? context.Content.ContentItem.ContentType : default(string);
|
||||||
var cacheKey = String.Format("LayoutElementTypes-{0}-{1}", contentType ?? "AnyType", context.CacheVaryParam);
|
var cacheKey = String.Format("LayoutElementTypes-{0}-{1}", contentType ?? "AnyType", context.CacheVaryParam);
|
||||||
return _cacheManager.Get(cacheKey, acquireContext => {
|
return _cacheManager.Get(cacheKey, true, acquireContext => {
|
||||||
var harvesterContext = new HarvestElementsContext {
|
var harvesterContext = new HarvestElementsContext {
|
||||||
Content = context.Content
|
Content = context.Content
|
||||||
};
|
};
|
||||||
@@ -55,7 +55,7 @@ namespace Orchard.Layouts.Services {
|
|||||||
|
|
||||||
public IEnumerable<CategoryDescriptor> GetCategories(DescribeElementsContext context) {
|
public IEnumerable<CategoryDescriptor> GetCategories(DescribeElementsContext context) {
|
||||||
var contentType = context.Content != null ? context.Content.ContentItem.ContentType : default(string);
|
var contentType = context.Content != null ? context.Content.ContentItem.ContentType : default(string);
|
||||||
return _cacheManager.Get(String.Format("ElementCategories-{0}-{1}", contentType ?? "AnyType", context.CacheVaryParam), acquireContext => {
|
return _cacheManager.Get(String.Format("ElementCategories-{0}-{1}", contentType ?? "AnyType", context.CacheVaryParam), true, acquireContext => {
|
||||||
var elements = DescribeElements(context);
|
var elements = DescribeElements(context);
|
||||||
var categoryDictionary = GetCategories();
|
var categoryDictionary = GetCategories();
|
||||||
var categoryDescriptorDictionary = new Dictionary<string, CategoryDescriptor>();
|
var categoryDescriptorDictionary = new Dictionary<string, CategoryDescriptor>();
|
||||||
|
@@ -5,17 +5,17 @@
|
|||||||
}
|
}
|
||||||
<div class="item-properties actions">
|
<div class="item-properties actions">
|
||||||
<p>
|
<p>
|
||||||
@Html.ActionLink(T("{0} Properties", (string)Model.ContainerDisplayName).ToString(), "Edit", new { Area = "Contents", Id = (int)Model.ContainerId, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl })
|
@Html.ActionLink(T("{0} Properties", (string)Model.ContainerDisplayName), "Edit", new { Area = "Contents", Id = (int)Model.ContainerId, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl })
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="manage">
|
<div class="manage">
|
||||||
@if (itemContentTypes.Any()) {
|
@if (itemContentTypes.Any()) {
|
||||||
foreach (var contentType in itemContentTypes) {
|
foreach (var contentType in itemContentTypes) {
|
||||||
@Html.ActionLink(T("New {0}", contentType.DisplayName).ToString(), "Create", "Admin", new { area = "Contents", id = contentType.Name, containerId }, new { @class = "button primaryAction create-content" })
|
@Html.ActionLink(T("New {0}", contentType.DisplayName), "Create", "Admin", new { area = "Contents", id = contentType.Name, containerId }, new { @class = "button primaryAction create-content" })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@Html.ActionLink(T("New Content").ToString(), "Create", "Admin", new { area = "Contents", containerId }, new { @class = "button primaryAction create-content" })
|
@Html.ActionLink(T("New Content"), "Create", "Admin", new { area = "Contents", containerId }, new { @class = "button primaryAction create-content" })
|
||||||
}
|
}
|
||||||
<a id="chooseItems" href="#" class="button primaryAction">@T("Choose Items")</a>
|
<a id="chooseItems" href="#" class="button primaryAction">@T("Choose Items")</a>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -58,7 +58,7 @@ namespace Orchard.MediaProcessing.Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private IDictionary<string, string> GetProfileCache(string profile) {
|
private IDictionary<string, string> GetProfileCache(string profile) {
|
||||||
return _cacheManager.Get("MediaProcessing_" + profile, ctx => {
|
return _cacheManager.Get("MediaProcessing_" + profile, true, ctx => {
|
||||||
ctx.Monitor(_signals.When("MediaProcessing_Saved_" + profile));
|
ctx.Monitor(_signals.When("MediaProcessing_Saved_" + profile));
|
||||||
var dictionary = new Dictionary<string, string>();
|
var dictionary = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@ namespace Orchard.MediaProcessing.Services {
|
|||||||
|
|
||||||
public ImageProfilePart GetImageProfileByName(string name) {
|
public ImageProfilePart GetImageProfileByName(string name) {
|
||||||
|
|
||||||
var profileId = _cacheManager.Get("ProfileId_" + name, ctx => {
|
var profileId = _cacheManager.Get("ProfileId_" + name, true, ctx => {
|
||||||
var profile = _contentManager.Query<ImageProfilePart, ImageProfilePartRecord>()
|
var profile = _contentManager.Query<ImageProfilePart, ImageProfilePartRecord>()
|
||||||
.Where(x => x.Name == name)
|
.Where(x => x.Name == name)
|
||||||
.Slice(0, 1)
|
.Slice(0, 1)
|
||||||
|
@@ -463,7 +463,7 @@ namespace Orchard.OutputCache.Filters {
|
|||||||
|
|
||||||
private CacheSettings CacheSettings {
|
private CacheSettings CacheSettings {
|
||||||
get {
|
get {
|
||||||
return _cacheSettings ?? (_cacheSettings = _cacheManager.Get(CacheSettings.CacheKey, context => {
|
return _cacheSettings ?? (_cacheSettings = _cacheManager.Get(CacheSettings.CacheKey, true, context => {
|
||||||
context.Monitor(_signals.When(CacheSettings.CacheKey));
|
context.Monitor(_signals.When(CacheSettings.CacheKey));
|
||||||
return new CacheSettings(_workContext.CurrentSite.As<CacheSettingsPart>());
|
return new CacheSettings(_workContext.CurrentSite.As<CacheSettingsPart>());
|
||||||
}));
|
}));
|
||||||
|
@@ -99,7 +99,7 @@ namespace Orchard.OutputCache.Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<CacheRouteConfig> GetRouteConfigs() {
|
public IEnumerable<CacheRouteConfig> GetRouteConfigs() {
|
||||||
return _cacheManager.Get(RouteConfigsCacheKey,
|
return _cacheManager.Get(RouteConfigsCacheKey, true,
|
||||||
ctx => {
|
ctx => {
|
||||||
ctx.Monitor(_signals.When(RouteConfigsCacheKey));
|
ctx.Monitor(_signals.When(RouteConfigsCacheKey));
|
||||||
return _repository.Fetch(c => true).Select(c => new CacheRouteConfig { RouteKey = c.RouteKey, Duration = c.Duration, GraceTime = c.GraceTime }).ToReadOnlyCollection();
|
return _repository.Fetch(c => true).Select(c => new CacheRouteConfig { RouteKey = c.RouteKey, Duration = c.Duration, GraceTime = c.GraceTime }).ToReadOnlyCollection();
|
||||||
|
@@ -14,7 +14,7 @@ namespace Orchard.Scripting.Dlr.Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public object Evaluate(string expression, IEnumerable<IGlobalMethodProvider> providers) {
|
public object Evaluate(string expression, IEnumerable<IGlobalMethodProvider> providers) {
|
||||||
object execContextType = _cacheManager.Get("---", ctx => (object)_scriptingManager.ExecuteExpression(@"
|
object execContextType = _cacheManager.Get("---", true, ctx => (object)_scriptingManager.ExecuteExpression(@"
|
||||||
class ExecBlock
|
class ExecBlock
|
||||||
def initialize(callbacks)
|
def initialize(callbacks)
|
||||||
@callbacks = callbacks
|
@callbacks = callbacks
|
||||||
@@ -38,7 +38,7 @@ class ExecContext
|
|||||||
end
|
end
|
||||||
ExecContext
|
ExecContext
|
||||||
"));
|
"));
|
||||||
var ops = _cacheManager.Get("----", ctx => (ObjectOperations)_scriptingManager.ExecuteOperation(x => x));
|
var ops = _cacheManager.Get("----", true, ctx => (ObjectOperations)_scriptingManager.ExecuteOperation(x => x));
|
||||||
object execContext = _cacheManager.Get(expression, ctx => (object)ops.InvokeMember(execContextType, "alloc", expression));
|
object execContext = _cacheManager.Get(expression, ctx => (object)ops.InvokeMember(execContextType, "alloc", expression));
|
||||||
dynamic result = ops.InvokeMember(execContext, "evaluate", new CallbackApi(this, providers));
|
dynamic result = ops.InvokeMember(execContext, "evaluate", new CallbackApi(this, providers));
|
||||||
return ConvertRubyValue(result);
|
return ConvertRubyValue(result);
|
||||||
|
@@ -20,7 +20,7 @@ namespace Orchard.Scripting {
|
|||||||
public Localizer T { get; set; }
|
public Localizer T { get; set; }
|
||||||
|
|
||||||
public object Evaluate(string expression, IEnumerable<IGlobalMethodProvider> providers) {
|
public object Evaluate(string expression, IEnumerable<IGlobalMethodProvider> providers) {
|
||||||
var expr = _cacheManager.Get(expression, ctx => {
|
var expr = _cacheManager.Get(expression, true, ctx => {
|
||||||
var ast = ParseExpression(expression);
|
var ast = ParseExpression(expression);
|
||||||
return new { Tree = ast, Errors = ast.GetErrors().ToList() };
|
return new { Tree = ast, Errors = ast.GetErrors().ToList() };
|
||||||
});
|
});
|
||||||
|
@@ -32,7 +32,7 @@ namespace Orchard.Tags.Services {
|
|||||||
|
|
||||||
public IEnumerable<TagCount> GetPopularTags(int buckets, string slug) {
|
public IEnumerable<TagCount> GetPopularTags(int buckets, string slug) {
|
||||||
var cacheKey = "Orchard.Tags.TagCloud." + (slug ?? "") + '.' + buckets;
|
var cacheKey = "Orchard.Tags.TagCloud." + (slug ?? "") + '.' + buckets;
|
||||||
return _cacheManager.Get(cacheKey,
|
return _cacheManager.Get(cacheKey, true,
|
||||||
ctx => {
|
ctx => {
|
||||||
ctx.Monitor(_signals.When(TagCloudTagsChanged));
|
ctx.Monitor(_signals.When(TagCloudTagsChanged));
|
||||||
IEnumerable<TagCount> tagCounts;
|
IEnumerable<TagCount> tagCounts;
|
||||||
|
@@ -31,21 +31,33 @@ namespace Orchard.Taxonomies.Tokens {
|
|||||||
|
|
||||||
context.For<TaxonomyField>("TaxonomyField")
|
context.For<TaxonomyField>("TaxonomyField")
|
||||||
.Token("Terms", field => String.Join(", ", field.Terms.Select(t => t.Name).ToArray()))
|
.Token("Terms", field => String.Join(", ", field.Terms.Select(t => t.Name).ToArray()))
|
||||||
.Token(
|
.Token(FilterTokenParam,
|
||||||
token => {
|
(index, field) => {
|
||||||
var index = 0;
|
var term = field.Terms.ElementAtOrDefault(Convert.ToInt32(index));
|
||||||
return (token.StartsWith("Terms:", StringComparison.OrdinalIgnoreCase) && int.TryParse(token.Substring("Terms:".Length), out index)) ? index.ToString() : null;
|
return term != null ? term.Name : null;
|
||||||
},
|
|
||||||
(token, t) => {
|
|
||||||
var index = Convert.ToInt32(token);
|
|
||||||
return index + 1 > t.Terms.Count() ? null : t.Terms.ElementAt(index).Name;
|
|
||||||
})
|
})
|
||||||
// todo: extend Chain() in order to accept a filter like in Token() so that we can chain on an expression
|
.Chain(FilterChainParam, "Content", (index, field) => field.Terms.ElementAtOrDefault(Convert.ToInt32(index)))
|
||||||
.Chain("Terms:0", "Content", t => t.Terms.ElementAt(0))
|
|
||||||
.Chain("Terms:1", "Content", t => t.Terms.ElementAt(1))
|
|
||||||
.Chain("Terms:2", "Content", t => t.Terms.ElementAt(2))
|
|
||||||
.Chain("Terms:3", "Content", t => t.Terms.ElementAt(3))
|
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string FilterTokenParam(string token) {
|
||||||
|
int index = 0;
|
||||||
|
return (token.StartsWith("Terms:", StringComparison.OrdinalIgnoreCase) && int.TryParse(token.Substring("Terms:".Length), out index)) ? index.ToString() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Tuple<string, string> FilterChainParam(string token) {
|
||||||
|
int tokenLength = "Terms:".Length;
|
||||||
|
int index = 0;
|
||||||
|
int chainIndex = token.IndexOf('.');
|
||||||
|
if (!token.StartsWith("Terms:", StringComparison.OrdinalIgnoreCase) || chainIndex <= tokenLength)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (int.TryParse(token.Substring(tokenLength, chainIndex - tokenLength), out index)) {
|
||||||
|
return new Tuple<string, string>(index.ToString(), token.Substring(chainIndex + 1));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -55,7 +55,7 @@ namespace Orchard.Templates.Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private IDictionary<string, TemplateResult> BuildShapeProcessors() {
|
private IDictionary<string, TemplateResult> BuildShapeProcessors() {
|
||||||
return _cacheManager.Get("Template.ShapeProcessors", ctx => {
|
return _cacheManager.Get("Template.ShapeProcessors", true, ctx => {
|
||||||
ctx.Monitor(_signals.When(DefaultTemplateService.TemplatesSignal));
|
ctx.Monitor(_signals.When(DefaultTemplateService.TemplatesSignal));
|
||||||
|
|
||||||
// select all name of types which contains ShapePart
|
// select all name of types which contains ShapePart
|
||||||
|
@@ -7,5 +7,6 @@ namespace Orchard.Tokens {
|
|||||||
public abstract EvaluateFor<TData> Chain(string token, string chainTarget, Func<TData, object> chainValue);
|
public abstract EvaluateFor<TData> Chain(string token, string chainTarget, Func<TData, object> chainValue);
|
||||||
public abstract EvaluateFor<TData> Token(Func<string, TData, object> tokenValue);
|
public abstract EvaluateFor<TData> Token(Func<string, TData, object> tokenValue);
|
||||||
public abstract EvaluateFor<TData> Token(Func<string, string> filter, Func<string, TData, object> tokenValue);
|
public abstract EvaluateFor<TData> Token(Func<string, string> filter, Func<string, TData, object> tokenValue);
|
||||||
|
public abstract EvaluateFor<TData> Chain(Func<string, Tuple<string, string>> filter, string chainTarget, Func<string, TData, object> chainValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -153,6 +153,27 @@ namespace Orchard.Tokens.Implementation {
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override EvaluateFor<TData> Chain(Func<string, Tuple<string, string>> filter, string chainTarget, Func<string, TData, object> chainValue) {
|
||||||
|
var subTokens = _context.Tokens
|
||||||
|
.Where(kv => kv.Key.Contains('.'))
|
||||||
|
.Select(kv => {
|
||||||
|
var filterResult = filter(kv.Key);
|
||||||
|
return filterResult != null ? new Tuple<string, string, string>(filterResult.Item1, filterResult.Item2, kv.Value) : null;
|
||||||
|
})
|
||||||
|
.Where(st => st != null)
|
||||||
|
.ToList();
|
||||||
|
if (!subTokens.Any()) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
foreach(var chainGroup in subTokens.GroupBy(st => st.Item1)) {
|
||||||
|
var subValues = _context._manager.Evaluate(chainTarget, chainGroup.ToDictionary(cg => cg.Item2, cg => cg.Item3), new Dictionary<string, object> { { chainTarget, chainValue(chainGroup.Key, _data) } });
|
||||||
|
foreach (var subValue in subValues) {
|
||||||
|
_context.Values[subValue.Key] = subValue.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class EvaluateForSilent<TData> : EvaluateFor<TData> {
|
private class EvaluateForSilent<TData> : EvaluateFor<TData> {
|
||||||
@@ -175,6 +196,10 @@ namespace Orchard.Tokens.Implementation {
|
|||||||
public override EvaluateFor<TData> Chain(string token, string chainTarget, Func<TData, object> chainValue) {
|
public override EvaluateFor<TData> Chain(string token, string chainTarget, Func<TData, object> chainValue) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override EvaluateFor<TData> Chain(Func<string, Tuple<string, string>> filter, string chainTarget, Func<string, TData, object> chainValue) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -36,7 +36,7 @@ namespace Orchard.Tokens.Providers {
|
|||||||
.Token("DisplayUrl", T("Display Url"), T("Url to display the content."), "Url")
|
.Token("DisplayUrl", T("Display Url"), T("Url to display the content."), "Url")
|
||||||
.Token("EditUrl", T("Edit Url"), T("Url to edit the content."), "Url")
|
.Token("EditUrl", T("Edit Url"), T("Url to edit the content."), "Url")
|
||||||
.Token("Container", T("Container"), T("The container Content Item."), "Content")
|
.Token("Container", T("Container"), T("The container Content Item."), "Content")
|
||||||
.Token("Body", T("Body"), T("The body text of the content item."), "Content")
|
.Token("Body", T("Body"), T("The body text of the content item."), "Text")
|
||||||
;
|
;
|
||||||
|
|
||||||
// Token descriptors for fields
|
// Token descriptors for fields
|
||||||
|
@@ -13,38 +13,45 @@ namespace Orchard.Tokens.Providers {
|
|||||||
public void Describe(DescribeContext context) {
|
public void Describe(DescribeContext context) {
|
||||||
context.For("Text", T("Text"), T("Tokens for text strings"))
|
context.For("Text", T("Text"), T("Tokens for text strings"))
|
||||||
.Token("Limit:*", T("Limit:<text length>[,<ellipsis>]"), T("Limit text to specified length and append an optional ellipsis text."))
|
.Token("Limit:*", T("Limit:<text length>[,<ellipsis>]"), T("Limit text to specified length and append an optional ellipsis text."))
|
||||||
.Token("Format:*", T("Format:<text format>"), T("Optional format specifier (e.g. foo{0}bar). See format strings at <a target=\"_blank\" href=\"http://msdn.microsoft.com/en-us/library/az4se3k1.aspx\">Standard Formats</a> and <a target=\"_blank\" href=\"http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx\">Custom Formats</a>"), "DateTime")
|
.Token("Format:*", T("Format:<text format>"), T("Optional format specifier (e.g. foo{0}bar)."))
|
||||||
.Token("TrimEnd:*", T("TrimEnd:<chars|number>"), T("Trims the specified characters or number of them from the end of the string."), "Text")
|
.Token("TrimEnd:*", T("TrimEnd:<chars|number>"), T("Trims the specified characters or number of them from the end of the string."))
|
||||||
.Token("UrlEncode", T("Url Encode"), T("Encodes a URL string."), "Text")
|
.Token("UrlEncode", T("Url Encode"), T("Encodes a URL string."), "Text")
|
||||||
.Token("HtmlEncode", T("Html Encode"), T("Encodes an HTML string."), "Text")
|
.Token("HtmlEncode", T("Html Encode"), T("Encodes an HTML string."), "Text")
|
||||||
.Token("LineEncode", T("Line Encode"), T("Replaces new lines with <br /> tags."))
|
.Token("JavaScriptEncode", T("JavaScript Encode"), T("Encodes a JavaScript string."), "Text")
|
||||||
|
.Token("LineEncode", T("Line Encode"), T("Replaces new lines with <br /> tags."), "Text")
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Evaluate(EvaluateContext context) {
|
public void Evaluate(EvaluateContext context) {
|
||||||
context.For<String>("Text", () => "")
|
context.For<String>("Text", () => "")
|
||||||
.Token( // {Text}
|
// {Text}
|
||||||
|
.Token(
|
||||||
token => token == String.Empty ? String.Empty : null,
|
token => token == String.Empty ? String.Empty : null,
|
||||||
(token, d) => d.ToString())
|
(token, d) => d.ToString())
|
||||||
.Token( // {Text.Limit:<length>[,<ellipsis>]}
|
// {Text.Limit:<length>[,<ellipsis>]}
|
||||||
token => {
|
.Token(
|
||||||
if (token.StartsWith("Limit:", StringComparison.OrdinalIgnoreCase)) {
|
token => FilterTokenParam("Limit:", token),
|
||||||
var param = token.Substring("Limit:".Length);
|
|
||||||
return param;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
(token, t) => Limit(t, token))
|
(token, t) => Limit(t, token))
|
||||||
// {Text.Format:<formatstring>}
|
// {Text.Format:<formatstring>}
|
||||||
.Token(
|
.Token(
|
||||||
token => token.StartsWith("Format:", StringComparison.OrdinalIgnoreCase) ? token.Substring("Format:".Length) : null,
|
token => FilterTokenParam("Format:", token),
|
||||||
(token, d) => String.Format(d,token))
|
(token, d) => String.Format(d, token))
|
||||||
.Token(token => token.StartsWith("TrimEnd:", StringComparison.OrdinalIgnoreCase) ? token.Substring("TrimEnd:".Length) : null, TrimEnd)
|
// {Text.TrimEnd:<chars|number>}
|
||||||
|
.Token(token => FilterTokenParam("TrimEnd:", token), TrimEnd)
|
||||||
.Token("UrlEncode", HttpUtility.UrlEncode)
|
.Token("UrlEncode", HttpUtility.UrlEncode)
|
||||||
|
.Chain("UrlEncode", "Text", HttpUtility.UrlEncode)
|
||||||
.Token("HtmlEncode", HttpUtility.HtmlEncode)
|
.Token("HtmlEncode", HttpUtility.HtmlEncode)
|
||||||
|
.Chain("HtmlEncode", "Text", HttpUtility.HtmlEncode)
|
||||||
|
.Token("JavaScriptEncode", HttpUtility.JavaScriptStringEncode)
|
||||||
|
.Chain("JavaScriptEncode", "Text", HttpUtility.JavaScriptStringEncode)
|
||||||
.Token("LineEncode", text => text.Replace(System.Environment.NewLine, "<br />"))
|
.Token("LineEncode", text => text.Replace(System.Environment.NewLine, "<br />"))
|
||||||
|
.Chain("LineEncode", "Text", text => text.Replace(System.Environment.NewLine, "<br />"))
|
||||||
;
|
;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FilterTokenParam(string tokenName, string token) {
|
||||||
|
return token.StartsWith(tokenName, StringComparison.OrdinalIgnoreCase) ? token.Substring(tokenName.Length) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string TrimEnd(string token, string param) {
|
private static string TrimEnd(string token, string param) {
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using Orchard.ContentManagement;
|
using Orchard.ContentManagement;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Security;
|
using Orchard.Security;
|
||||||
@@ -24,6 +25,9 @@ namespace Orchard.Tokens.Tests {
|
|||||||
|
|
||||||
context.For("Date")
|
context.For("Date")
|
||||||
.Token("Now", T("Now"), T("Current system date in short date format. You can chain a .NET DateTime format string to customize."));
|
.Token("Now", T("Now"), T("Current system date in short date format. You can chain a .NET DateTime format string to customize."));
|
||||||
|
|
||||||
|
context.For("Users")
|
||||||
|
.Token("Users[*:]", T("Users"), T("A user by its username"), "User");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Evaluate(EvaluateContext context) {
|
public void Evaluate(EvaluateContext context) {
|
||||||
@@ -36,6 +40,7 @@ namespace Orchard.Tokens.Tests {
|
|||||||
|
|
||||||
context.For<IUser>("User", () => new TestUser { UserName = "CurrentUser" })
|
context.For<IUser>("User", () => new TestUser { UserName = "CurrentUser" })
|
||||||
.Token("Name", u => u.UserName)
|
.Token("Name", u => u.UserName)
|
||||||
|
.Token("Email", u => u.Email)
|
||||||
.Token("Birthdate", u => "Nov 15")
|
.Token("Birthdate", u => "Nov 15")
|
||||||
.Chain("Birthdate", "DateTime", u => new DateTime(1978, 11, 15));
|
.Chain("Birthdate", "DateTime", u => new DateTime(1978, 11, 15));
|
||||||
|
|
||||||
@@ -45,6 +50,29 @@ namespace Orchard.Tokens.Tests {
|
|||||||
|
|
||||||
context.For<DateTime>("DateTime")
|
context.For<DateTime>("DateTime")
|
||||||
.Token((token, value) => value.ToString(token));
|
.Token((token, value) => value.ToString(token));
|
||||||
|
|
||||||
|
context.For<TestUser[]>("Users", () => new TestUser[] {
|
||||||
|
new TestUser { UserName = "User1", Email = "user1@test.com" },
|
||||||
|
new TestUser { UserName = "User2", Email = "user2@test.com" },
|
||||||
|
new TestUser { UserName = "User3", Email = "user3@test.com" }
|
||||||
|
})
|
||||||
|
.Token(
|
||||||
|
(token) => token.StartsWith("User:", StringComparison.OrdinalIgnoreCase) ? token.Substring("User:".Length) : null,
|
||||||
|
(userName, users) => users.Where(u => u.UserName == userName).Select(u => u.UserName).FirstOrDefault()
|
||||||
|
)
|
||||||
|
.Chain(
|
||||||
|
(token) => {
|
||||||
|
int tokenLength = "User:".Length;
|
||||||
|
int chainIndex = token.IndexOf('.');
|
||||||
|
if (token.StartsWith("User:", StringComparison.OrdinalIgnoreCase) && chainIndex > tokenLength)
|
||||||
|
return new Tuple<string, string>(token.Substring(tokenLength, chainIndex - tokenLength), token.Substring(chainIndex + 1));
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
"User",
|
||||||
|
(userName, users) => users.Where(u => u.UserName == userName).FirstOrDefault()
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -29,10 +29,11 @@ namespace Orchard.Tokens.Tests {
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestDescribe() {
|
public void TestDescribe() {
|
||||||
var allTokens = _tokenManager.Describe(null);
|
var allTokens = _tokenManager.Describe(null);
|
||||||
Assert.That(allTokens.Count(), Is.EqualTo(3));
|
Assert.That(allTokens.Count(), Is.EqualTo(4));
|
||||||
Assert.That(allTokens.Any(d => d.Target == "Site"));
|
Assert.That(allTokens.Any(d => d.Target == "Site"));
|
||||||
Assert.That(allTokens.Any(d => d.Target == "User"));
|
Assert.That(allTokens.Any(d => d.Target == "User"));
|
||||||
Assert.That(allTokens.Any(d => d.Target == "Date"));
|
Assert.That(allTokens.Any(d => d.Target == "Date"));
|
||||||
|
Assert.That(allTokens.Any(d => d.Target == "Users"));
|
||||||
|
|
||||||
var tokens = allTokens.Single(d => d.Target == "Site").Tokens;
|
var tokens = allTokens.Single(d => d.Target == "Site").Tokens;
|
||||||
Assert.That(string.Join(",", tokens.Select(td => td.Target)), Is.EqualTo("Site,Site,Site,Site"));
|
Assert.That(string.Join(",", tokens.Select(td => td.Target)), Is.EqualTo("Site,Site,Site,Site"));
|
||||||
@@ -59,7 +60,7 @@ namespace Orchard.Tokens.Tests {
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestDescribeFilter() {
|
public void TestDescribeFilter() {
|
||||||
var tokenDescriptors = _tokenManager.Describe(null);
|
var tokenDescriptors = _tokenManager.Describe(null);
|
||||||
Assert.That(tokenDescriptors.Count(), Is.EqualTo(3));
|
Assert.That(tokenDescriptors.Count(), Is.EqualTo(4));
|
||||||
tokenDescriptors = _tokenManager.Describe(new[] { "Site" });
|
tokenDescriptors = _tokenManager.Describe(new[] { "Site" });
|
||||||
Assert.That(tokenDescriptors.Count(), Is.EqualTo(1));
|
Assert.That(tokenDescriptors.Count(), Is.EqualTo(1));
|
||||||
Assert.That(tokenDescriptors.First().Target, Is.EqualTo("Site"));
|
Assert.That(tokenDescriptors.First().Target, Is.EqualTo("Site"));
|
||||||
|
@@ -40,6 +40,18 @@ namespace Orchard.Tokens.Tests {
|
|||||||
Assert.That(_tokenizer.Replace("{Site.CurrentUser.Birthdate.yyyy}", null), Is.EqualTo("1978"));
|
Assert.That(_tokenizer.Replace("{Site.CurrentUser.Birthdate.yyyy}", null), Is.EqualTo("1978"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestParameterizedTokens() {
|
||||||
|
Assert.That(_tokenizer.Replace("{Users.User:User2}", null), Is.EqualTo("User2"));
|
||||||
|
Assert.That(_tokenizer.Replace("{Users.User:FakeUser}", null), Is.EqualTo(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestParameterizedChainedTokens() {
|
||||||
|
Assert.That(_tokenizer.Replace("{Users.User:User2.Email}", null), Is.EqualTo("user2@test.com"));
|
||||||
|
Assert.That(_tokenizer.Replace("{Users.User:FakeUser.Email}", null), Is.EqualTo(""));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestMissingTokens() {
|
public void TestMissingTokens() {
|
||||||
Assert.That(_tokenizer.Replace("[{Site.NotAToken}]", null), Is.EqualTo("[]"));
|
Assert.That(_tokenizer.Replace("[{Site.NotAToken}]", null), Is.EqualTo("[]"));
|
||||||
|
@@ -255,14 +255,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Layouts", "Orchard.
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.DynamicForms", "Orchard.Web\Modules\Orchard.DynamicForms\Orchard.DynamicForms.csproj", "{82190F52-2901-46D6-8A4C-34649959483F}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.DynamicForms", "Orchard.Web\Modules\Orchard.DynamicForms\Orchard.DynamicForms.csproj", "{82190F52-2901-46D6-8A4C-34649959483F}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Dashboards", "Orchard.Web\Modules\Orchard.Dashboards\Orchard.Dashboards.csproj", "{BAC82DB9-F4C4-4DD1-ABDB-F70E6229E6B0}"
|
||||||
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DF3909B0-1DDD-4D8A-9919-56FC438E25E2}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DF3909B0-1DDD-4D8A-9919-56FC438E25E2}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
Rebracer.xml = Rebracer.xml
|
Rebracer.xml = Rebracer.xml
|
||||||
WebEssentials-Settings.json = WebEssentials-Settings.json
|
WebEssentials-Settings.json = WebEssentials-Settings.json
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Dashboards", "Orchard.Web\Modules\Orchard.Dashboards\Orchard.Dashboards.csproj", "{BAC82DB9-F4C4-4DD1-ABDB-F70E6229E6B0}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gulp", "Gulp", "{90EBEE36-B5CD-42A8-A21B-76270E2C5D24}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gulp", "Gulp", "{90EBEE36-B5CD-42A8-A21B-76270E2C5D24}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
Gulpfile.js = Gulpfile.js
|
Gulpfile.js = Gulpfile.js
|
||||||
|
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Caching {
|
namespace Orchard.Caching {
|
||||||
public class DefaultAsyncTokenProvider : IAsyncTokenProvider {
|
public class DefaultAsyncTokenProvider : IAsyncTokenProvider {
|
||||||
@@ -37,9 +38,12 @@ namespace Orchard.Caching {
|
|||||||
try {
|
try {
|
||||||
_task(token => _taskTokens.Add(token));
|
_task(token => _taskTokens.Add(token));
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
Logger.Error(e, "Error while monitoring extension files. Assuming extensions are not current.");
|
if (ex.IsFatal()) {
|
||||||
_taskException = e;
|
throw;
|
||||||
|
}
|
||||||
|
Logger.Error(ex, "Error while monitoring extension files. Assuming extensions are not current.");
|
||||||
|
_taskException = ex;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
_isTaskFinished = true;
|
_isTaskFinished = true;
|
||||||
|
@@ -5,4 +5,17 @@ namespace Orchard.Caching {
|
|||||||
TResult Get<TKey, TResult>(TKey key, Func<AcquireContext<TKey>, TResult> acquire);
|
TResult Get<TKey, TResult>(TKey key, Func<AcquireContext<TKey>, TResult> acquire);
|
||||||
ICache<TKey, TResult> GetCache<TKey, TResult>();
|
ICache<TKey, TResult> GetCache<TKey, TResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class CacheManagerExtensions {
|
||||||
|
public static TResult Get<TKey, TResult>(this ICacheManager cacheManager, TKey key, bool lazy, Func<AcquireContext<TKey>, TResult> acquire) {
|
||||||
|
// Wrap the call in a Lazy initializer to prevent multiple processes from
|
||||||
|
// executing the same lambda in parallel.
|
||||||
|
if (lazy) {
|
||||||
|
return cacheManager.Get<TKey, Lazy<TResult>>(key, k => new Lazy<TResult>(() => acquire(k))).Value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return cacheManager.Get(key, acquire);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,7 @@ using Orchard.FileSystems.VirtualPath;
|
|||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
using Orchard.Tasks;
|
using Orchard.Tasks;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Commands {
|
namespace Orchard.Commands {
|
||||||
|
|
||||||
@@ -94,19 +95,21 @@ namespace Orchard.Commands {
|
|||||||
|
|
||||||
return CommandReturnCodes.Ok;
|
return CommandReturnCodes.Ok;
|
||||||
}
|
}
|
||||||
catch (OrchardCommandHostRetryException e) {
|
catch (OrchardCommandHostRetryException ex) {
|
||||||
// Special "Retry" return code for our host
|
// Special "Retry" return code for our host
|
||||||
output.WriteLine(T("{0} (Retrying...)", e.Message));
|
output.WriteLine(T("{0} (Retrying...)", ex.Message));
|
||||||
return CommandReturnCodes.Retry;
|
return CommandReturnCodes.Retry;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
if (e is TargetInvocationException &&
|
if (ex.IsFatal()) {
|
||||||
e.InnerException != null) {
|
throw;
|
||||||
// If this is an exception coming from reflection and there is an innerexception which is the actual one, redirect
|
|
||||||
e = e.InnerException;
|
|
||||||
}
|
}
|
||||||
|
if (ex is TargetInvocationException &&
|
||||||
OutputException(output, T("Error executing command \"{0}\"", string.Join(" ", args)), e);
|
ex.InnerException != null) {
|
||||||
|
// If this is an exception coming from reflection and there is an innerexception which is the actual one, redirect
|
||||||
|
ex = ex.InnerException;
|
||||||
|
}
|
||||||
|
OutputException(output, T("Error executing command \"{0}\"", string.Join(" ", args)), ex);
|
||||||
return CommandReturnCodes.Fail;
|
return CommandReturnCodes.Fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,13 +119,16 @@ namespace Orchard.Commands {
|
|||||||
_hostContainer = CreateHostContainer();
|
_hostContainer = CreateHostContainer();
|
||||||
return CommandReturnCodes.Ok;
|
return CommandReturnCodes.Ok;
|
||||||
}
|
}
|
||||||
catch (OrchardCommandHostRetryException e) {
|
catch (OrchardCommandHostRetryException ex) {
|
||||||
// Special "Retry" return code for our host
|
// Special "Retry" return code for our host
|
||||||
output.WriteLine(T("{0} (Retrying...)", e.Message));
|
output.WriteLine(T("{0} (Retrying...)", ex.Message));
|
||||||
return CommandReturnCodes.Retry;
|
return CommandReturnCodes.Retry;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
OutputException(output, T("Error starting up Orchard command line host"), e);
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
OutputException(output, T("Error starting up Orchard command line host"), ex);
|
||||||
return CommandReturnCodes.Fail;
|
return CommandReturnCodes.Fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,8 +141,11 @@ namespace Orchard.Commands {
|
|||||||
}
|
}
|
||||||
return CommandReturnCodes.Ok;
|
return CommandReturnCodes.Ok;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
OutputException(output, T("Error shutting down Orchard command line host"), e);
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
OutputException(output, T("Error shutting down Orchard command line host"), ex);
|
||||||
return CommandReturnCodes.Fail;
|
return CommandReturnCodes.Fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Commands {
|
namespace Orchard.Commands {
|
||||||
public abstract class DefaultOrchardCommandHandler : ICommandHandler {
|
public abstract class DefaultOrchardCommandHandler : ICommandHandler {
|
||||||
@@ -41,12 +42,15 @@ namespace Orchard.Commands {
|
|||||||
object value = Convert.ChangeType(commandSwitch.Value, propertyInfo.PropertyType);
|
object value = Convert.ChangeType(commandSwitch.Value, propertyInfo.PropertyType);
|
||||||
propertyInfo.SetValue(this, value, null/*index*/);
|
propertyInfo.SetValue(this, value, null/*index*/);
|
||||||
}
|
}
|
||||||
catch(Exception e) {
|
catch(Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
string message = T("Error converting value \"{0}\" to \"{1}\" for switch \"{2}\"",
|
string message = T("Error converting value \"{0}\" to \"{1}\" for switch \"{2}\"",
|
||||||
LocalizedString.TextOrDefault(commandSwitch.Value, T("(empty)")),
|
LocalizedString.TextOrDefault(commandSwitch.Value, T("(empty)")),
|
||||||
propertyInfo.PropertyType.FullName,
|
propertyInfo.PropertyType.FullName,
|
||||||
commandSwitch.Key).Text;
|
commandSwitch.Key).Text;
|
||||||
throw new InvalidOperationException(message, e);
|
throw new InvalidOperationException(message, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -817,7 +817,7 @@ namespace Orchard.ContentManagement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ContentTypeRecord AcquireContentTypeRecord(string contentType) {
|
private ContentTypeRecord AcquireContentTypeRecord(string contentType) {
|
||||||
var contentTypeId = _cacheManager.Get(contentType + "_Record", ctx => {
|
var contentTypeId = _cacheManager.Get(contentType + "_Record", true, ctx => {
|
||||||
ctx.Monitor(_signals.When(contentType + "_Record"));
|
ctx.Monitor(_signals.When(contentType + "_Record"));
|
||||||
|
|
||||||
var contentTypeRecord = _contentTypeRepository.Get(x => x.Name == contentType);
|
var contentTypeRecord = _contentTypeRepository.Get(x => x.Name == contentType);
|
||||||
|
@@ -76,7 +76,7 @@ namespace Orchard.ContentManagement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int GetContentTypeRecordId(string contentType) {
|
private int GetContentTypeRecordId(string contentType) {
|
||||||
return _cacheManager.Get(contentType + "_Record", ctx => {
|
return _cacheManager.Get(contentType + "_Record", true, ctx => {
|
||||||
ctx.Monitor(_signals.When(contentType + "_Record"));
|
ctx.Monitor(_signals.When(contentType + "_Record"));
|
||||||
|
|
||||||
var contentTypeRecord = _contentTypeRepository.Get(x => x.Name == contentType);
|
var contentTypeRecord = _contentTypeRepository.Get(x => x.Name == contentType);
|
||||||
|
@@ -1,9 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Orchard.Data.Migration.Interpreters;
|
||||||
|
using Orchard.Data.Migration.Schema;
|
||||||
using Orchard.Environment;
|
using Orchard.Environment;
|
||||||
|
using Orchard.Environment.Configuration;
|
||||||
using Orchard.Environment.Features;
|
using Orchard.Environment.Features;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
using Orchard.Tasks.Locking.Services;
|
using Orchard.Tasks.Locking.Services;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Data.Migration {
|
namespace Orchard.Data.Migration {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -13,24 +17,35 @@ namespace Orchard.Data.Migration {
|
|||||||
private readonly IDataMigrationManager _dataMigrationManager;
|
private readonly IDataMigrationManager _dataMigrationManager;
|
||||||
private readonly IFeatureManager _featureManager;
|
private readonly IFeatureManager _featureManager;
|
||||||
private readonly IDistributedLockService _distributedLockService;
|
private readonly IDistributedLockService _distributedLockService;
|
||||||
|
private readonly IDataMigrationInterpreter _dataMigrationInterpreter;
|
||||||
|
private readonly ShellSettings _shellSettings;
|
||||||
|
private readonly ITransactionManager _transactionManager;
|
||||||
|
|
||||||
public AutomaticDataMigrations(
|
public AutomaticDataMigrations(
|
||||||
IDataMigrationManager dataMigrationManager,
|
IDataMigrationManager dataMigrationManager,
|
||||||
|
IDataMigrationInterpreter dataMigrationInterpreter,
|
||||||
IFeatureManager featureManager,
|
IFeatureManager featureManager,
|
||||||
IDistributedLockService distributedLockService) {
|
IDistributedLockService distributedLockService,
|
||||||
|
ITransactionManager transactionManager,
|
||||||
|
ShellSettings shellSettings) {
|
||||||
|
|
||||||
_dataMigrationManager = dataMigrationManager;
|
_dataMigrationManager = dataMigrationManager;
|
||||||
_featureManager = featureManager;
|
_featureManager = featureManager;
|
||||||
_distributedLockService = distributedLockService;
|
_distributedLockService = distributedLockService;
|
||||||
|
_shellSettings = shellSettings;
|
||||||
|
_transactionManager = transactionManager;
|
||||||
|
_dataMigrationInterpreter = dataMigrationInterpreter;
|
||||||
|
|
||||||
Logger = NullLogger.Instance;
|
Logger = NullLogger.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ILogger Logger { get; set; }
|
public ILogger Logger { get; set; }
|
||||||
|
|
||||||
public void Activated() {
|
public void Activated() {
|
||||||
|
EnsureDistributedLockSchemaExists();
|
||||||
|
|
||||||
IDistributedLock @lock;
|
IDistributedLock @lock;
|
||||||
if(_distributedLockService.TryAcquireLock(GetType().FullName, TimeSpan.FromMinutes(30), TimeSpan.FromMilliseconds(250), out @lock)) {
|
if (_distributedLockService.TryAcquireLock(GetType().FullName, TimeSpan.FromMinutes(30), TimeSpan.FromMilliseconds(250), out @lock)) {
|
||||||
using (@lock) {
|
using (@lock) {
|
||||||
// Let's make sure that the basic set of features is enabled. If there are any that are not enabled, then let's enable them first.
|
// Let's make sure that the basic set of features is enabled. If there are any that are not enabled, then let's enable them first.
|
||||||
var theseFeaturesShouldAlwaysBeActive = new[] {
|
var theseFeaturesShouldAlwaysBeActive = new[] {
|
||||||
@@ -48,7 +63,10 @@ namespace Orchard.Data.Migration {
|
|||||||
_dataMigrationManager.Update(feature);
|
_dataMigrationManager.Update(feature);
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
Logger.Error(ex, "Could not run migrations automatically on {0}.", feature);
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
Logger.Error("Could not run migrations automatically on " + feature, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,5 +76,16 @@ namespace Orchard.Data.Migration {
|
|||||||
public void Terminating() {
|
public void Terminating() {
|
||||||
// No-op.
|
// No-op.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This ensures that the framework migrations have run for the distributed locking feature, as existing Orchard installations will not have the required tables when upgrading.
|
||||||
|
/// </summary>
|
||||||
|
private void EnsureDistributedLockSchemaExists() {
|
||||||
|
// Ensure the distributed lock record schema exists.
|
||||||
|
var schemaBuilder = new SchemaBuilder(_dataMigrationInterpreter);
|
||||||
|
var distributedLockSchemaBuilder = new DistributedLockSchemaBuilder(_shellSettings, schemaBuilder);
|
||||||
|
if (distributedLockSchemaBuilder.EnsureSchema())
|
||||||
|
_transactionManager.RequireNew();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@ using Orchard.Data.Migration.Schema;
|
|||||||
using Orchard.Environment.Extensions;
|
using Orchard.Environment.Extensions;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Data.Migration {
|
namespace Orchard.Data.Migration {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -123,6 +124,9 @@ namespace Orchard.Data.Migration {
|
|||||||
current = (int)lookupTable[current].Invoke(migration, new object[0]);
|
current = (int)lookupTable[current].Invoke(migration, new object[0]);
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
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;
|
throw;
|
||||||
}
|
}
|
||||||
@@ -139,10 +143,13 @@ namespace Orchard.Data.Migration {
|
|||||||
dataMigrationRecord.Version = current;
|
dataMigrationRecord.Version = current;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
Logger.Error(e, "Error while running migration version {0} for {1}.", current, feature);
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
Logger.Error(ex, "Error while running migration version {0} for {1}.", current, feature);
|
||||||
_transactionManager.Cancel();
|
_transactionManager.Cancel();
|
||||||
throw new OrchardException(T("Error while running migration version {0} for {1}.", current, feature), e);
|
throw new OrchardException(T("Error while running migration version {0} for {1}.", current, feature), ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using Orchard.Data.Migration.Interpreters;
|
using Orchard.Data.Migration.Interpreters;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Data.Migration.Schema {
|
namespace Orchard.Data.Migration.Schema {
|
||||||
public class SchemaBuilder {
|
public class SchemaBuilder {
|
||||||
@@ -72,6 +73,9 @@ namespace Orchard.Data.Migration.Schema {
|
|||||||
Run(sqlStatmentCommand);
|
Run(sqlStatmentCommand);
|
||||||
return this;
|
return this;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
throw new OrchardException(T("An unexpected error occured while executing the SQL statement: {0}", sql), ex); // Add the sql to the nested exception information
|
throw new OrchardException(T("An unexpected error occured while executing the SQL statement: {0}", sql), ex); // Add the sql to the nested exception information
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,7 @@ using Orchard.Environment.ShellBuilders.Models;
|
|||||||
using Orchard.FileSystems.AppData;
|
using Orchard.FileSystems.AppData;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
using Orchard.Utility;
|
using Orchard.Utility;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Data {
|
namespace Orchard.Data {
|
||||||
public class SessionConfigurationCache : ISessionConfigurationCache {
|
public class SessionConfigurationCache : ISessionConfigurationCache {
|
||||||
@@ -80,11 +81,11 @@ namespace Orchard.Data {
|
|||||||
formatter.Serialize(stream, cache.Configuration);
|
formatter.Serialize(stream, cache.Configuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (SerializationException e) {
|
catch (SerializationException ex) {
|
||||||
//Note: This can happen when multiple processes/AppDomains try to save
|
//Note: This can happen when multiple processes/AppDomains try to save
|
||||||
// the cached configuration at the same time. Only one concurrent
|
// the cached configuration at the same time. Only one concurrent
|
||||||
// writer will win, and it's harmless for the other ones to fail.
|
// writer will win, and it's harmless for the other ones to fail.
|
||||||
for (Exception scan = e; scan != null; scan = scan.InnerException)
|
for (Exception scan = ex; scan != null; scan = scan.InnerException)
|
||||||
Logger.Warning("Error storing new NHibernate cache configuration: {0}", scan.Message);
|
Logger.Warning("Error storing new NHibernate cache configuration: {0}", scan.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,8 +119,11 @@ namespace Orchard.Data {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
for (var scan = e; scan != null; scan = scan.InnerException)
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
for (var scan = ex; scan != null; scan = scan.InnerException)
|
||||||
Logger.Warning("Error reading the cached NHibernate configuration: {0}", scan.Message);
|
Logger.Warning("Error reading the cached NHibernate configuration: {0}", scan.Message);
|
||||||
Logger.Information("A new one will be re-generated.");
|
Logger.Information("A new one will be re-generated.");
|
||||||
return null;
|
return null;
|
||||||
|
@@ -37,7 +37,7 @@ namespace Orchard.DisplayManagement.Descriptors {
|
|||||||
public ILogger Logger { get; set; }
|
public ILogger Logger { get; set; }
|
||||||
|
|
||||||
public ShapeTable GetShapeTable(string themeName) {
|
public ShapeTable GetShapeTable(string themeName) {
|
||||||
return _cacheManager.Get(themeName ?? "", x => {
|
return _cacheManager.Get(themeName ?? "", true, x => {
|
||||||
Logger.Information("Start building shape table");
|
Logger.Information("Start building shape table");
|
||||||
|
|
||||||
var alterationSets = _parallelCacheContext.RunInParallel(_bindingStrategies, bindingStrategy => {
|
var alterationSets = _parallelCacheContext.RunInParallel(_bindingStrategies, bindingStrategy => {
|
||||||
|
@@ -30,7 +30,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapePlacementStrategy {
|
|||||||
public bool DisableMonitoring { get; set; }
|
public bool DisableMonitoring { get; set; }
|
||||||
|
|
||||||
public PlacementFile Parse(string virtualPath) {
|
public PlacementFile Parse(string virtualPath) {
|
||||||
return _cacheManager.Get(virtualPath, context => {
|
return _cacheManager.Get(virtualPath, true, context => {
|
||||||
|
|
||||||
if (!DisableMonitoring) {
|
if (!DisableMonitoring) {
|
||||||
Logger.Debug("Monitoring virtual path \"{0}\"", virtualPath);
|
Logger.Debug("Monitoring virtual path \"{0}\"", virtualPath);
|
||||||
|
@@ -77,7 +77,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy {
|
|||||||
var pathContexts = harvesterInfos.SelectMany(harvesterInfo => harvesterInfo.subPaths.Select(subPath => {
|
var pathContexts = harvesterInfos.SelectMany(harvesterInfo => harvesterInfo.subPaths.Select(subPath => {
|
||||||
var basePath = Path.Combine(extensionDescriptor.Location, extensionDescriptor.Id).Replace(Path.DirectorySeparatorChar, '/');
|
var basePath = Path.Combine(extensionDescriptor.Location, extensionDescriptor.Id).Replace(Path.DirectorySeparatorChar, '/');
|
||||||
var virtualPath = Path.Combine(basePath, subPath).Replace(Path.DirectorySeparatorChar, '/');
|
var virtualPath = Path.Combine(basePath, subPath).Replace(Path.DirectorySeparatorChar, '/');
|
||||||
var fileNames = _cacheManager.Get(virtualPath, ctx => {
|
var fileNames = _cacheManager.Get(virtualPath, true, ctx => {
|
||||||
if (!_virtualPathProvider.DirectoryExists(virtualPath))
|
if (!_virtualPathProvider.DirectoryExists(virtualPath))
|
||||||
return new List<string>();
|
return new List<string>();
|
||||||
|
|
||||||
|
@@ -14,6 +14,7 @@ using Orchard.Logging;
|
|||||||
using Orchard.Mvc;
|
using Orchard.Mvc;
|
||||||
using Orchard.Mvc.Extensions;
|
using Orchard.Mvc.Extensions;
|
||||||
using Orchard.Utility.Extensions;
|
using Orchard.Utility.Extensions;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Environment {
|
namespace Orchard.Environment {
|
||||||
// All the event handlers that DefaultOrchardHost implements have to be declared in OrchardStarter.
|
// All the event handlers that DefaultOrchardHost implements have to be declared in OrchardStarter.
|
||||||
@@ -145,8 +146,11 @@ namespace Orchard.Environment {
|
|||||||
var context = CreateShellContext(settings, StandaloneEnvironmentOptions.None);
|
var context = CreateShellContext(settings, StandaloneEnvironmentOptions.None);
|
||||||
ActivateShell(context);
|
ActivateShell(context);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
Logger.Error(e, "A tenant could not be started: " + settings.Name);
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
Logger.Error(ex, "A tenant could not be started: " + settings.Name);
|
||||||
}
|
}
|
||||||
while (_processingEngine.AreTasksPending()) {
|
while (_processingEngine.AreTasksPending()) {
|
||||||
Logger.Debug("Processing pending task after activate Shell");
|
Logger.Debug("Processing pending task after activate Shell");
|
||||||
|
@@ -11,6 +11,7 @@ using Orchard.Owin;
|
|||||||
using Orchard.Tasks;
|
using Orchard.Tasks;
|
||||||
using Orchard.UI;
|
using Orchard.UI;
|
||||||
using Orchard.WebApi.Routes;
|
using Orchard.WebApi.Routes;
|
||||||
|
using Orchard.Exceptions;
|
||||||
using IModelBinderProvider = Orchard.Mvc.ModelBinders.IModelBinderProvider;
|
using IModelBinderProvider = Orchard.Mvc.ModelBinders.IModelBinderProvider;
|
||||||
|
|
||||||
namespace Orchard.Environment {
|
namespace Orchard.Environment {
|
||||||
@@ -98,8 +99,12 @@ namespace Orchard.Environment {
|
|||||||
try {
|
try {
|
||||||
action();
|
action();
|
||||||
}
|
}
|
||||||
catch(Exception e) {
|
catch(Exception ex) {
|
||||||
Logger.Error(e, "An unexcepted error occured while terminating the Shell");
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Error(ex, "An unexcepted error occured while terminating the Shell");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@ using Orchard.FileSystems.Dependencies;
|
|||||||
using Orchard.FileSystems.VirtualPath;
|
using Orchard.FileSystems.VirtualPath;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Environment.Extensions.Compilers {
|
namespace Orchard.Environment.Extensions.Compilers {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -106,10 +107,13 @@ namespace Orchard.Environment.Extensions.Compilers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
//Note: we need to embed the "e.Message" in the exception text because
|
//Note: we need to embed the "e.Message" in the exception text because
|
||||||
// ASP.NET build manager "swallows" inner exceptions from this method.
|
// ASP.NET build manager "swallows" inner exceptions from this method.
|
||||||
throw new OrchardCoreException(T("Error compiling module \"{0}\" from file \"{1}\":\r\n{2}", moduleName, context.VirtualPath, e.Message), e);
|
throw new OrchardCoreException(T("Error compiling module \"{0}\" from file \"{1}\":\r\n{2}", moduleName, context.VirtualPath, ex.Message), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,7 +23,7 @@ namespace Orchard.Environment.Extensions.Compilers {
|
|||||||
public bool DisableMonitoring { get; set; }
|
public bool DisableMonitoring { get; set; }
|
||||||
|
|
||||||
public ProjectFileDescriptor Parse(string virtualPath) {
|
public ProjectFileDescriptor Parse(string virtualPath) {
|
||||||
return _cacheManager.Get(virtualPath,
|
return _cacheManager.Get(virtualPath, true,
|
||||||
ctx => {
|
ctx => {
|
||||||
if (!DisableMonitoring) {
|
if (!DisableMonitoring) {
|
||||||
Logger.Debug("Monitoring virtual path \"{0}\"", virtualPath);
|
Logger.Debug("Monitoring virtual path \"{0}\"", virtualPath);
|
||||||
|
@@ -9,6 +9,7 @@ using Orchard.Localization;
|
|||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
using Orchard.Utility;
|
using Orchard.Utility;
|
||||||
using Orchard.Utility.Extensions;
|
using Orchard.Utility.Extensions;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Environment.Extensions {
|
namespace Orchard.Environment.Extensions {
|
||||||
public class ExtensionManager : IExtensionManager {
|
public class ExtensionManager : IExtensionManager {
|
||||||
@@ -44,7 +45,7 @@ namespace Orchard.Environment.Extensions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<ExtensionDescriptor> AvailableExtensions() {
|
public IEnumerable<ExtensionDescriptor> AvailableExtensions() {
|
||||||
return _cacheManager.Get("AvailableExtensions", ctx =>
|
return _cacheManager.Get("AvailableExtensions", true, ctx =>
|
||||||
_parallelCacheContext
|
_parallelCacheContext
|
||||||
.RunInParallel(_folders, folder => folder.AvailableExtensions().ToList())
|
.RunInParallel(_folders, folder => folder.AvailableExtensions().ToList())
|
||||||
.SelectMany(descriptors => descriptors)
|
.SelectMany(descriptors => descriptors)
|
||||||
@@ -52,7 +53,7 @@ namespace Orchard.Environment.Extensions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<FeatureDescriptor> AvailableFeatures() {
|
public IEnumerable<FeatureDescriptor> AvailableFeatures() {
|
||||||
return _cacheManager.Get("AvailableFeatures", ctx =>
|
return _cacheManager.Get("AvailableFeatures", true, ctx =>
|
||||||
AvailableExtensions()
|
AvailableExtensions()
|
||||||
.SelectMany(ext => ext.Features)
|
.SelectMany(ext => ext.Features)
|
||||||
.OrderByDependenciesAndPriorities(HasDependency, GetPriority)
|
.OrderByDependenciesAndPriorities(HasDependency, GetPriority)
|
||||||
@@ -92,7 +93,7 @@ namespace Orchard.Environment.Extensions {
|
|||||||
|
|
||||||
var result =
|
var result =
|
||||||
_parallelCacheContext
|
_parallelCacheContext
|
||||||
.RunInParallel(featureDescriptors, descriptor => _cacheManager.Get(descriptor.Id, ctx => LoadFeature(descriptor)))
|
.RunInParallel(featureDescriptors, descriptor => _cacheManager.Get(descriptor.Id, true, ctx => LoadFeature(descriptor)))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
Logger.Information("Done loading features");
|
Logger.Information("Done loading features");
|
||||||
@@ -106,7 +107,7 @@ namespace Orchard.Environment.Extensions {
|
|||||||
|
|
||||||
ExtensionEntry extensionEntry;
|
ExtensionEntry extensionEntry;
|
||||||
try {
|
try {
|
||||||
extensionEntry = _cacheManager.Get(extensionId, ctx => {
|
extensionEntry = _cacheManager.Get(extensionId, true, ctx => {
|
||||||
var entry = BuildEntry(extensionDescriptor);
|
var entry = BuildEntry(extensionDescriptor);
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
ctx.Monitor(_asyncTokenProvider.GetToken(monitor => {
|
ctx.Monitor(_asyncTokenProvider.GetToken(monitor => {
|
||||||
@@ -119,6 +120,9 @@ namespace Orchard.Environment.Extensions {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
Logger.Error(ex, "Error loading extension '{0}'", extensionId);
|
Logger.Error(ex, "Error loading extension '{0}'", extensionId);
|
||||||
throw new OrchardException(T("Error while loading extension '{0}'.", extensionId), ex);
|
throw new OrchardException(T("Error while loading extension '{0}'.", extensionId), ex);
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@ using Orchard.FileSystems.WebSite;
|
|||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
using Orchard.Utility.Extensions;
|
using Orchard.Utility.Extensions;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Environment.Extensions.Folders {
|
namespace Orchard.Environment.Extensions.Folders {
|
||||||
public class ExtensionHarvester : IExtensionHarvester {
|
public class ExtensionHarvester : IExtensionHarvester {
|
||||||
@@ -57,7 +58,7 @@ namespace Orchard.Environment.Extensions.Folders {
|
|||||||
private IEnumerable<ExtensionDescriptor> HarvestExtensions(string path, string extensionType, string manifestName, bool manifestIsOptional) {
|
private IEnumerable<ExtensionDescriptor> HarvestExtensions(string path, string extensionType, string manifestName, bool manifestIsOptional) {
|
||||||
string key = string.Format("{0}-{1}-{2}", path, manifestName, extensionType);
|
string key = string.Format("{0}-{1}-{2}", path, manifestName, extensionType);
|
||||||
|
|
||||||
return _cacheManager.Get(key, ctx => {
|
return _cacheManager.Get(key, true, ctx => {
|
||||||
if (!DisableMonitoring) {
|
if (!DisableMonitoring) {
|
||||||
Logger.Debug("Monitoring virtual path \"{0}\"", path);
|
Logger.Debug("Monitoring virtual path \"{0}\"", path);
|
||||||
ctx.Monitor(_webSiteFolder.WhenPathChanges(path));
|
ctx.Monitor(_webSiteFolder.WhenPathChanges(path));
|
||||||
@@ -100,6 +101,9 @@ namespace Orchard.Environment.Extensions.Folders {
|
|||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
// Ignore invalid module manifests
|
// Ignore invalid module manifests
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
Logger.Error(ex, "The module '{0}' could not be loaded. It was ignored.", extensionId);
|
Logger.Error(ex, "The module '{0}' could not be loaded. It was ignored.", extensionId);
|
||||||
_criticalErrorProvider.RegisterErrorMessage(T("The extension '{0}' manifest could not be loaded. It was ignored.", extensionId));
|
_criticalErrorProvider.RegisterErrorMessage(T("The extension '{0}' manifest could not be loaded. It was ignored.", extensionId));
|
||||||
}
|
}
|
||||||
@@ -134,7 +138,7 @@ namespace Orchard.Environment.Extensions.Folders {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ExtensionDescriptor GetExtensionDescriptor(string locationPath, string extensionId, string extensionType, string manifestPath, bool manifestIsOptional) {
|
private ExtensionDescriptor GetExtensionDescriptor(string locationPath, string extensionId, string extensionType, string manifestPath, bool manifestIsOptional) {
|
||||||
return _cacheManager.Get(manifestPath, context => {
|
return _cacheManager.Get(manifestPath, true, context => {
|
||||||
if (!DisableMonitoring) {
|
if (!DisableMonitoring) {
|
||||||
Logger.Debug("Monitoring virtual path \"{0}\"", manifestPath);
|
Logger.Debug("Monitoring virtual path \"{0}\"", manifestPath);
|
||||||
context.Monitor(_webSiteFolder.WhenPathChanges(manifestPath));
|
context.Monitor(_webSiteFolder.WhenPathChanges(manifestPath));
|
||||||
|
@@ -4,6 +4,8 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
|
|
||||||
namespace Orchard.Environment {
|
namespace Orchard.Environment {
|
||||||
public interface IAssemblyLoader {
|
public interface IAssemblyLoader {
|
||||||
@@ -25,8 +27,11 @@ namespace Orchard.Environment {
|
|||||||
try {
|
try {
|
||||||
return _loadedAssemblies.GetOrAdd(this.ExtractAssemblyShortName(assemblyName), shortName => LoadWorker(shortName, assemblyName));
|
return _loadedAssemblies.GetOrAdd(this.ExtractAssemblyShortName(assemblyName), shortName => LoadWorker(shortName, assemblyName));
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
Logger.Error(e, "Error loading assembly '{0}'", assemblyName);
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
Logger.Error(ex, "Error loading assembly '{0}'", assemblyName);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,7 @@ namespace Orchard.Environment {
|
|||||||
public string Resolve(string shortName) {
|
public string Resolve(string shortName) {
|
||||||
// A few common .net framework assemblies are referenced by the Orchard.Framework assembly.
|
// A few common .net framework assemblies are referenced by the Orchard.Framework assembly.
|
||||||
// Look into those to see if we can find the assembly we are looking for.
|
// Look into those to see if we can find the assembly we are looking for.
|
||||||
var orchardFrameworkReferences = _cacheManager.Get(typeof(IAssemblyLoader), ctx =>
|
var orchardFrameworkReferences = _cacheManager.Get(typeof(IAssemblyLoader), true, ctx =>
|
||||||
ctx.Key.Assembly
|
ctx.Key.Assembly
|
||||||
.GetReferencedAssemblies()
|
.GetReferencedAssemblies()
|
||||||
.GroupBy(n => AssemblyLoaderExtensions.ExtractAssemblyShortName(n.FullName), StringComparer.OrdinalIgnoreCase)
|
.GroupBy(n => AssemblyLoaderExtensions.ExtractAssemblyShortName(n.FullName), StringComparer.OrdinalIgnoreCase)
|
||||||
|
@@ -53,8 +53,9 @@ namespace Orchard.Environment {
|
|||||||
return BuildManager.GetCompiledAssembly(virtualPath);
|
return BuildManager.GetCompiledAssembly(virtualPath);
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
if (ex.IsFatal()) throw;
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
Logger.Warning(ex, "Error when compiling assembly under {0}.", virtualPath);
|
Logger.Warning(ex, "Error when compiling assembly under {0}.", virtualPath);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@ using Orchard.Environment.Descriptor;
|
|||||||
using Orchard.Environment.Descriptor.Models;
|
using Orchard.Environment.Descriptor.Models;
|
||||||
using Orchard.FileSystems.AppData;
|
using Orchard.FileSystems.AppData;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Environment {
|
namespace Orchard.Environment {
|
||||||
public interface IHostLocalRestart {
|
public interface IHostLocalRestart {
|
||||||
@@ -45,8 +46,11 @@ namespace Orchard.Environment {
|
|||||||
try {
|
try {
|
||||||
_appDataFolder.CreateFile(fileName, "Host Restart");
|
_appDataFolder.CreateFile(fileName, "Host Restart");
|
||||||
}
|
}
|
||||||
catch(Exception e) {
|
catch(Exception ex) {
|
||||||
Logger.Warning(e, "Error updating file '{0}'", fileName);
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
Logger.Warning(ex, "Error updating file '{0}'", fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,7 @@ using System.Timers;
|
|||||||
using System.Web.Compilation;
|
using System.Web.Compilation;
|
||||||
using Orchard.FileSystems.VirtualPath;
|
using Orchard.FileSystems.VirtualPath;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Environment {
|
namespace Orchard.Environment {
|
||||||
public interface IViewsBackgroundCompilation {
|
public interface IViewsBackgroundCompilation {
|
||||||
@@ -136,10 +137,13 @@ namespace Orchard.Environment {
|
|||||||
if (firstFile != null)
|
if (firstFile != null)
|
||||||
BuildManager.GetCompiledAssembly(firstFile);
|
BuildManager.GetCompiledAssembly(firstFile);
|
||||||
}
|
}
|
||||||
catch(Exception e) {
|
catch(Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
// Some views might not compile, this is ok and harmless in this
|
// Some views might not compile, this is ok and harmless in this
|
||||||
// context of pre-compiling views.
|
// context of pre-compiling views.
|
||||||
Logger.Information(e, "Compilation of directory '{0}' skipped", viewDirectory);
|
Logger.Information(ex, "Compilation of directory '{0}' skipped", viewDirectory);
|
||||||
}
|
}
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
Logger.Information("Directory '{0}' compiled in {1} msec", viewDirectory, stopwatch.ElapsedMilliseconds);
|
Logger.Information("Directory '{0}' compiled in {1} msec", viewDirectory, stopwatch.ElapsedMilliseconds);
|
||||||
|
@@ -53,6 +53,9 @@ namespace Orchard.Events {
|
|||||||
return TryInvoke(eventHandler, messageName, interfaceName, methodName, eventData, out returnValue);
|
return TryInvoke(eventHandler, messageName, interfaceName, methodName, eventData, out returnValue);
|
||||||
}
|
}
|
||||||
catch (Exception exception) {
|
catch (Exception exception) {
|
||||||
|
if (exception.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
if (!_exceptionPolicy.HandleException(this, exception)) {
|
if (!_exceptionPolicy.HandleException(this, exception)) {
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,7 @@ using Orchard.FileSystems.VirtualPath;
|
|||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
using Orchard.Validation;
|
using Orchard.Validation;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.FileSystems.AppData {
|
namespace Orchard.FileSystems.AppData {
|
||||||
public class AppDataFolder : IAppDataFolder {
|
public class AppDataFolder : IAppDataFolder {
|
||||||
@@ -78,8 +79,11 @@ namespace Orchard.FileSystems.AppData {
|
|||||||
try {
|
try {
|
||||||
File.Delete(destinationFileName);
|
File.Delete(destinationFileName);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
throw new OrchardCoreException(T("Unable to make room for file \"{0}\" in \"App_Data\" folder", destinationFileName), e);
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
throw new OrchardCoreException(T("Unable to make room for file \"{0}\" in \"App_Data\" folder", destinationFileName), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,7 +34,7 @@ namespace Orchard.FileSystems.Dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<DependencyDescriptor> LoadDescriptors() {
|
public IEnumerable<DependencyDescriptor> LoadDescriptors() {
|
||||||
return _cacheManager.Get(PersistencePath,
|
return _cacheManager.Get(PersistencePath, true,
|
||||||
ctx => {
|
ctx => {
|
||||||
_appDataFolder.CreateDirectory(BasePath);
|
_appDataFolder.CreateDirectory(BasePath);
|
||||||
|
|
||||||
|
@@ -5,6 +5,7 @@ using System.Xml.Linq;
|
|||||||
using Orchard.Caching;
|
using Orchard.Caching;
|
||||||
using Orchard.FileSystems.AppData;
|
using Orchard.FileSystems.AppData;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.FileSystems.Dependencies {
|
namespace Orchard.FileSystems.Dependencies {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -64,7 +65,7 @@ namespace Orchard.FileSystems.Dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<ActivatedExtensionDescriptor> LoadDescriptors() {
|
public IEnumerable<ActivatedExtensionDescriptor> LoadDescriptors() {
|
||||||
return _cacheManager.Get(PersistencePath, ctx => {
|
return _cacheManager.Get(PersistencePath, true, ctx => {
|
||||||
_appDataFolder.CreateDirectory(BasePath);
|
_appDataFolder.CreateDirectory(BasePath);
|
||||||
|
|
||||||
if (!DisableMonitoring) {
|
if (!DisableMonitoring) {
|
||||||
@@ -135,8 +136,11 @@ namespace Orchard.FileSystems.Dependencies {
|
|||||||
return XDocument.Load(stream);
|
return XDocument.Load(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
Logger.Information(e, "Error reading file '{0}'. Assuming empty.", persistancePath);
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
Logger.Information(ex, "Error reading file '{0}'. Assuming empty.", persistancePath);
|
||||||
return new XDocument();
|
return new XDocument();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,7 @@ using System.Web.Hosting;
|
|||||||
using Orchard.Environment.Configuration;
|
using Orchard.Environment.Configuration;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Validation;
|
using Orchard.Validation;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.FileSystems.Media {
|
namespace Orchard.FileSystems.Media {
|
||||||
public class FileSystemStorageProvider : IStorageProvider {
|
public class FileSystemStorageProvider : IStorageProvider {
|
||||||
@@ -155,6 +156,9 @@ namespace Orchard.FileSystems.Media {
|
|||||||
directoryInfo.Create();
|
directoryInfo.Create();
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
throw new ArgumentException(T("The folder could not be created at path: {0}. {1}", path, ex).ToString());
|
throw new ArgumentException(T("The folder could not be created at path: {0}. {1}", path, ex).ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Hosting;
|
using System.Web.Hosting;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.FileSystems.VirtualPath {
|
namespace Orchard.FileSystems.VirtualPath {
|
||||||
public class DefaultVirtualPathProvider : IVirtualPathProvider {
|
public class DefaultVirtualPathProvider : IVirtualPathProvider {
|
||||||
@@ -59,9 +60,12 @@ namespace Orchard.FileSystems.VirtualPath {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
// The initial path might have been invalid (e.g. path indicates a path outside the application root)
|
// The initial path might have been invalid (e.g. path indicates a path outside the application root)
|
||||||
Logger.Information(e, "Path '{0}' cannot be made app relative", virtualPath);
|
Logger.Information(ex, "Path '{0}' cannot be made app relative", virtualPath);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,8 +160,11 @@ namespace Orchard.FileSystems.VirtualPath {
|
|||||||
try {
|
try {
|
||||||
return FileExists(virtualPath);
|
return FileExists(virtualPath);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
Logger.Information(e, "File '{0}' can not be checked for existence. Assuming doesn't exist.", virtualPath);
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
Logger.Information(ex, "File '{0}' can not be checked for existence. Assuming doesn't exist.", virtualPath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -26,7 +26,7 @@ namespace Orchard.Localization.Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<string> ListCultures() {
|
public IEnumerable<string> ListCultures() {
|
||||||
return _cacheManager.Get("Cultures", context => {
|
return _cacheManager.Get("Cultures", true, context => {
|
||||||
context.Monitor(_signals.When("culturesChanged"));
|
context.Monitor(_signals.When("culturesChanged"));
|
||||||
|
|
||||||
return _cultureRepository.Table.Select(o => o.Culture).ToList();
|
return _cultureRepository.Table.Select(o => o.Culture).ToList();
|
||||||
|
@@ -90,7 +90,7 @@ namespace Orchard.Localization.Services {
|
|||||||
// Cache entry will be invalidated any time the directories hosting
|
// Cache entry will be invalidated any time the directories hosting
|
||||||
// the .po files are modified.
|
// the .po files are modified.
|
||||||
private CultureDictionary LoadCulture(string culture) {
|
private CultureDictionary LoadCulture(string culture) {
|
||||||
return _cacheManager.Get(culture, ctx => {
|
return _cacheManager.Get(culture, true, ctx => {
|
||||||
ctx.Monitor(_signals.When("culturesChanged"));
|
ctx.Monitor(_signals.When("culturesChanged"));
|
||||||
return new CultureDictionary {
|
return new CultureDictionary {
|
||||||
CultureName = culture,
|
CultureName = culture,
|
||||||
|
@@ -5,6 +5,7 @@ using Orchard.Logging;
|
|||||||
using Orchard.Messaging.Events;
|
using Orchard.Messaging.Events;
|
||||||
using Orchard.Messaging.Models;
|
using Orchard.Messaging.Models;
|
||||||
using Orchard.ContentManagement.Records;
|
using Orchard.ContentManagement.Records;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Messaging.Services {
|
namespace Orchard.Messaging.Services {
|
||||||
[Obsolete]
|
[Obsolete]
|
||||||
@@ -40,8 +41,11 @@ namespace Orchard.Messaging.Services {
|
|||||||
|
|
||||||
PrepareAndSend(type, properties, context);
|
PrepareAndSend(type, properties, context);
|
||||||
}
|
}
|
||||||
catch ( Exception e ) {
|
catch (Exception ex) {
|
||||||
Logger.Error(e, "An error occured while sending the message {0}", type);
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
Logger.Error(ex, "An error occured while sending the message {0}", type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,8 +64,11 @@ namespace Orchard.Messaging.Services {
|
|||||||
|
|
||||||
PrepareAndSend(type, properties, context);
|
PrepareAndSend(type, properties, context);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
Logger.Error(e, "An error occured while sending the message {0}", type);
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
Logger.Error(ex, "An error occured while sending the message {0}", type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
144
src/Orchard/Mvc/Html/LinkExtensions.cs
Normal file
144
src/Orchard/Mvc/Html/LinkExtensions.cs
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Web;
|
||||||
|
using System.Web.Mvc;
|
||||||
|
using System.Web.Routing;
|
||||||
|
using System.Web.WebPages;
|
||||||
|
|
||||||
|
namespace Orchard.Mvc.Html {
|
||||||
|
public static class LinkExtensions {
|
||||||
|
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName) {
|
||||||
|
return ActionLink(htmlHelper, linkText, actionName, null /* controllerName */, new RouteValueDictionary(), new RouteValueDictionary());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, object routeValues) {
|
||||||
|
return ActionLink(htmlHelper, linkText, actionName, null /* controllerName */, ObjectToDictionary(routeValues), new RouteValueDictionary());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, object routeValues, object htmlAttributes) {
|
||||||
|
return ActionLink(htmlHelper, linkText, actionName, null /* controllerName */, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, RouteValueDictionary routeValues) {
|
||||||
|
return ActionLink(htmlHelper, linkText, actionName, null /* controllerName */, routeValues, new RouteValueDictionary());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes) {
|
||||||
|
return ActionLink(htmlHelper, linkText, actionName, null /* controllerName */, routeValues, htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, string controllerName) {
|
||||||
|
return ActionLink(htmlHelper, linkText, actionName, controllerName, new RouteValueDictionary(), new RouteValueDictionary());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, string controllerName, object routeValues, object htmlAttributes) {
|
||||||
|
return ActionLink(htmlHelper, linkText, actionName, controllerName, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes) {
|
||||||
|
if (String.IsNullOrEmpty(linkText.ToString())) {
|
||||||
|
throw new ArgumentException("Argument must be a non empty string", "linkText");
|
||||||
|
}
|
||||||
|
return MvcHtmlString.Create(GenerateLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, null /* routeName */, actionName, controllerName, routeValues, htmlAttributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, object routeValues, object htmlAttributes) {
|
||||||
|
return ActionLink(htmlHelper, linkText, actionName, controllerName, protocol, hostName, fragment, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes) {
|
||||||
|
if (String.IsNullOrEmpty(linkText.ToString())) {
|
||||||
|
throw new ArgumentException("Argument must be a non empty string", "linkText");
|
||||||
|
}
|
||||||
|
return MvcHtmlString.Create(GenerateLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, null /* routeName */, actionName, controllerName, protocol, hostName, fragment, routeValues, htmlAttributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, object routeValues) {
|
||||||
|
return RouteLink(htmlHelper, linkText, ObjectToDictionary(routeValues));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, RouteValueDictionary routeValues) {
|
||||||
|
return RouteLink(htmlHelper, linkText, routeValues, new RouteValueDictionary());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName) {
|
||||||
|
return RouteLink(htmlHelper, linkText, routeName, (object)null /* routeValues */);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, object routeValues) {
|
||||||
|
return RouteLink(htmlHelper, linkText, routeName, ObjectToDictionary(routeValues));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, RouteValueDictionary routeValues) {
|
||||||
|
return RouteLink(htmlHelper, linkText, routeName, routeValues, new RouteValueDictionary());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, object routeValues, object htmlAttributes) {
|
||||||
|
return RouteLink(htmlHelper, linkText, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes) {
|
||||||
|
return RouteLink(htmlHelper, linkText, null /* routeName */, routeValues, htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, object routeValues, object htmlAttributes) {
|
||||||
|
return RouteLink(htmlHelper, linkText, routeName, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes) {
|
||||||
|
if (String.IsNullOrEmpty(linkText.ToString())) {
|
||||||
|
throw new ArgumentException("Argument must be a non empty string", "linkText");
|
||||||
|
}
|
||||||
|
return MvcHtmlString.Create(GenerateRouteLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, routeName, routeValues, htmlAttributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, string protocol, string hostName, string fragment, object routeValues, object htmlAttributes) {
|
||||||
|
return RouteLink(htmlHelper, linkText, routeName, protocol, hostName, fragment, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes) {
|
||||||
|
if (String.IsNullOrEmpty(linkText.ToString())) {
|
||||||
|
throw new ArgumentException("Argument must be a non empty string", "linkText");
|
||||||
|
}
|
||||||
|
return MvcHtmlString.Create(GenerateRouteLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, routeName, protocol, hostName, fragment, routeValues, htmlAttributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GenerateLink(RequestContext requestContext, RouteCollection routeCollection, IHtmlString linkText, string routeName, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes) {
|
||||||
|
return GenerateLink(requestContext, routeCollection, linkText, routeName, actionName, controllerName, null /* protocol */, null /* hostName */, null /* fragment */, routeValues, htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GenerateLink(RequestContext requestContext, RouteCollection routeCollection, IHtmlString linkText, string routeName, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes) {
|
||||||
|
return GenerateLinkInternal(requestContext, routeCollection, linkText, routeName, actionName, controllerName, protocol, hostName, fragment, routeValues, htmlAttributes, true /* includeImplicitMvcValues */);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GenerateRouteLink(RequestContext requestContext, RouteCollection routeCollection, IHtmlString linkText, string routeName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes) {
|
||||||
|
return GenerateRouteLink(requestContext, routeCollection, linkText, routeName, null /* protocol */, null /* hostName */, null /* fragment */, routeValues, htmlAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GenerateRouteLink(RequestContext requestContext, RouteCollection routeCollection, IHtmlString linkText, string routeName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes) {
|
||||||
|
return GenerateLinkInternal(requestContext, routeCollection, linkText, routeName, null /* actionName */, null /* controllerName */, protocol, hostName, fragment, routeValues, htmlAttributes, false /* includeImplicitMvcValues */);
|
||||||
|
}
|
||||||
|
private static string GenerateLinkInternal(RequestContext requestContext, RouteCollection routeCollection, IHtmlString linkText, string routeName, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes, bool includeImplicitMvcValues) {
|
||||||
|
string url = UrlHelper.GenerateUrl(routeName, actionName, controllerName, protocol, hostName, fragment, routeValues, routeCollection, requestContext, includeImplicitMvcValues);
|
||||||
|
TagBuilder tagBuilder = new TagBuilder("a") {
|
||||||
|
InnerHtml = linkText.ToString()
|
||||||
|
};
|
||||||
|
tagBuilder.MergeAttributes(htmlAttributes);
|
||||||
|
tagBuilder.MergeAttribute("href", url);
|
||||||
|
return tagBuilder.ToString(TagRenderMode.Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RouteValueDictionary ObjectToDictionary(object value) {
|
||||||
|
RouteValueDictionary dictionary = new RouteValueDictionary();
|
||||||
|
|
||||||
|
if (value != null) {
|
||||||
|
foreach (var prop in value.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) {
|
||||||
|
dictionary.Add(prop.Name, prop.GetValue(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dictionary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -11,6 +11,7 @@ using System.Web.Routing;
|
|||||||
using Autofac;
|
using Autofac;
|
||||||
using Orchard.Mvc.Routes;
|
using Orchard.Mvc.Routes;
|
||||||
using Orchard.Settings;
|
using Orchard.Settings;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Mvc {
|
namespace Orchard.Mvc {
|
||||||
public class MvcModule : Module {
|
public class MvcModule : Module {
|
||||||
@@ -31,7 +32,11 @@ namespace Orchard.Mvc {
|
|||||||
// The "Request" property throws at application startup on IIS integrated pipeline mode.
|
// The "Request" property throws at application startup on IIS integrated pipeline mode.
|
||||||
var req = HttpContext.Current.Request;
|
var req = HttpContext.Current.Request;
|
||||||
}
|
}
|
||||||
catch (Exception) {
|
catch (Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -188,6 +188,7 @@
|
|||||||
<Compile Include="Security\IMembershipValidationService.cs" />
|
<Compile Include="Security\IMembershipValidationService.cs" />
|
||||||
<Compile Include="Localization\Services\ILocalizationStreamParser.cs" />
|
<Compile Include="Localization\Services\ILocalizationStreamParser.cs" />
|
||||||
<Compile Include="Localization\Services\LocalizationStreamParser.cs" />
|
<Compile Include="Localization\Services\LocalizationStreamParser.cs" />
|
||||||
|
<Compile Include="Mvc\Html\LinkExtensions.cs" />
|
||||||
<Compile Include="Security\ISslSettingsProvider.cs" />
|
<Compile Include="Security\ISslSettingsProvider.cs" />
|
||||||
<Compile Include="Security\NullMembershipService.cs" />
|
<Compile Include="Security\NullMembershipService.cs" />
|
||||||
<Compile Include="Security\Providers\DefaultSslSettingsProvider.cs" />
|
<Compile Include="Security\Providers\DefaultSslSettingsProvider.cs" />
|
||||||
@@ -401,7 +402,7 @@
|
|||||||
<Compile Include="Services\IJsonConverter.cs" />
|
<Compile Include="Services\IJsonConverter.cs" />
|
||||||
<Compile Include="Settings\CurrentSiteWorkContext.cs" />
|
<Compile Include="Settings\CurrentSiteWorkContext.cs" />
|
||||||
<Compile Include="Settings\ResourceDebugMode.cs" />
|
<Compile Include="Settings\ResourceDebugMode.cs" />
|
||||||
<Compile Include="Tasks\Locking\Migrations\FrameworkMigrations.cs" />
|
<Compile Include="Tasks\Locking\Services\DistributedLockSchemaBuilder.cs" />
|
||||||
<Compile Include="Tasks\Locking\Services\IDistributedLock.cs" />
|
<Compile Include="Tasks\Locking\Services\IDistributedLock.cs" />
|
||||||
<Compile Include="Tasks\Locking\Services\DistributedLock.cs" />
|
<Compile Include="Tasks\Locking\Services\DistributedLock.cs" />
|
||||||
<Compile Include="Tasks\Locking\Services\IDistributedLockService.cs" />
|
<Compile Include="Tasks\Locking\Services\IDistributedLockService.cs" />
|
||||||
|
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using Orchard.Data;
|
using Orchard.Data;
|
||||||
using Orchard.Environment.Configuration;
|
using Orchard.Environment.Configuration;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Tasks {
|
namespace Orchard.Tasks {
|
||||||
|
|
||||||
@@ -39,9 +40,13 @@ namespace Orchard.Tasks {
|
|||||||
task.Sweep();
|
task.Sweep();
|
||||||
Logger.Information("Finished processing background task \"{0}\" on tenant \"{1}\".", taskName, _shellName);
|
Logger.Information("Finished processing background task \"{0}\" on tenant \"{1}\".", taskName, _shellName);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
_transactionManager.Cancel();
|
_transactionManager.Cancel();
|
||||||
Logger.Error(e, "Error while processing background task \"{0}\" on tenant \"{1}\".", taskName, _shellName);
|
Logger.Error(ex, "Error while processing background task \"{0}\" on tenant \"{1}\".", taskName, _shellName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,22 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Orchard.Data.Migration;
|
|
||||||
|
|
||||||
namespace Orchard.Tasks.Locking.Migrations {
|
|
||||||
public class FrameworkMigrations : DataMigrationImpl {
|
|
||||||
|
|
||||||
public int Create() {
|
|
||||||
SchemaBuilder.CreateTable("DistributedLockRecord", table => table
|
|
||||||
.Column<int>("Id", column => column.PrimaryKey().Identity())
|
|
||||||
.Column<string>("Name", column => column.NotNull().WithLength(512).Unique())
|
|
||||||
.Column<string>("MachineName", column => column.WithLength(256))
|
|
||||||
.Column<DateTime>("CreatedUtc")
|
|
||||||
.Column<DateTime>("ValidUntilUtc", column => column.Nullable()));
|
|
||||||
|
|
||||||
SchemaBuilder.AlterTable("DistributedLockRecord", table => {
|
|
||||||
table.CreateIndex("IDX_DistributedLockRecord_Name", "Name");
|
|
||||||
});
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using Orchard.Data.Migration.Schema;
|
||||||
|
using Orchard.Environment.Configuration;
|
||||||
|
|
||||||
|
namespace Orchard.Tasks.Locking.Services {
|
||||||
|
public class DistributedLockSchemaBuilder {
|
||||||
|
private readonly ShellSettings _shellSettings;
|
||||||
|
private readonly SchemaBuilder _schemaBuilder;
|
||||||
|
private const string TableName = "Orchard_Framework_DistributedLockRecord";
|
||||||
|
|
||||||
|
public DistributedLockSchemaBuilder(ShellSettings shellSettings, SchemaBuilder schemaBuilder) {
|
||||||
|
_shellSettings = shellSettings;
|
||||||
|
_schemaBuilder = schemaBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool EnsureSchema() {
|
||||||
|
if (SchemaExists())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CreateSchema();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateSchema() {
|
||||||
|
_schemaBuilder.CreateTable(TableName, table => table
|
||||||
|
.Column<int>("Id", column => column.PrimaryKey().Identity())
|
||||||
|
.Column<string>("Name", column => column.NotNull().WithLength(512).Unique())
|
||||||
|
.Column<string>("MachineName", column => column.WithLength(256))
|
||||||
|
.Column<DateTime>("CreatedUtc")
|
||||||
|
.Column<DateTime>("ValidUntilUtc", column => column.Nullable()));
|
||||||
|
|
||||||
|
_schemaBuilder.AlterTable(TableName, table => {
|
||||||
|
table.CreateIndex("IDX_DistributedLockRecord_Name", "Name");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SchemaExists() {
|
||||||
|
try {
|
||||||
|
var tablePrefix = String.IsNullOrEmpty(_shellSettings.DataTablePrefix) ? "" : _shellSettings.DataTablePrefix + "_";
|
||||||
|
_schemaBuilder.ExecuteSql(String.Format("select * from {0}{1}", tablePrefix, TableName));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -44,30 +44,30 @@ namespace Orchard.Tasks.Locking.Services {
|
|||||||
if (dLock != null) {
|
if (dLock != null) {
|
||||||
Logger.Debug("Successfully acquired lock '{0}'.", name);
|
Logger.Debug("Successfully acquired lock '{0}'.", name);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Warning("Failed to acquire lock '{0}' within the specified timeout ({1}).", name, timeout);
|
Logger.Warning("Failed to acquire lock '{0}' within the specified timeout ({1}).", name, timeout);
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
Logger.Error(ex, "Error while trying to acquire lock '{0}'.", name);
|
Logger.Error(ex, "Error while trying to acquire lock '{0}'.", name);
|
||||||
// TODO: Is it correct to not throw here? Should we instead ONLY swallow TimeoutException?
|
// TODO: Is it correct to not throw here? Should we instead ONLY swallow TimeoutException?
|
||||||
}
|
}
|
||||||
|
|
||||||
dLock = null;
|
dLock = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDistributedLock AcquireLock(string name, TimeSpan? maxValidFor, TimeSpan? timeout) {
|
public IDistributedLock AcquireLock(string name, TimeSpan? maxValidFor, TimeSpan? timeout) {
|
||||||
try {
|
try {
|
||||||
DistributedLock result = AcquireLockInternal(name, maxValidFor, timeout, throwOnTimeout: true);
|
DistributedLock result = AcquireLockInternal(name, maxValidFor, timeout, throwOnTimeout: true);
|
||||||
Logger.Debug("Successfully acquired lock '{0}'.", name);
|
Logger.Debug("Successfully acquired lock '{0}'.", name);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
Logger.Error(ex, "Error while trying to acquire lock '{0}'.", name);
|
Logger.Error(ex, "Error while trying to acquire lock '{0}'.", name);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DistributedLock AcquireLockInternal(string name, TimeSpan? maxValidFor, TimeSpan? timeout, bool throwOnTimeout) {
|
private DistributedLock AcquireLockInternal(string name, TimeSpan? maxValidFor, TimeSpan? timeout, bool throwOnTimeout) {
|
||||||
var internalName = GetInternalLockName(name);
|
var internalName = GetInternalLockName(name);
|
||||||
@@ -81,7 +81,7 @@ namespace Orchard.Tasks.Locking.Services {
|
|||||||
throw new TimeoutException(String.Format("Failed to acquire lock '{0}' within the specified timeout ({1}).", internalName, timeout));
|
throw new TimeoutException(String.Format("Failed to acquire lock '{0}' within the specified timeout ({1}).", internalName, timeout));
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Debug("Successfully entered local monitor for lock '{0}'.", internalName);
|
Logger.Debug("Successfully entered local monitor for lock '{0}'.", internalName);
|
||||||
|
|
||||||
@@ -106,34 +106,34 @@ namespace Orchard.Tasks.Locking.Services {
|
|||||||
dLock = new DistributedLock(name, internalName, releaseLockAction: () => {
|
dLock = new DistributedLock(name, internalName, releaseLockAction: () => {
|
||||||
Monitor.Exit(monitorObj);
|
Monitor.Exit(monitorObj);
|
||||||
DeleteDistributedLockRecord(internalName);
|
DeleteDistributedLockRecord(internalName);
|
||||||
});
|
});
|
||||||
|
|
||||||
_locks.Add(monitorObj, dLock);
|
_locks.Add(monitorObj, dLock);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
Logger.Debug("Record for lock '{0}' could not be created for current machine within the specified timeout ({1}).", internalName, timeout);
|
Logger.Debug("Record for lock '{0}' could not be created for current machine within the specified timeout ({1}).", internalName, timeout);
|
||||||
|
|
||||||
if (throwOnTimeout)
|
if (throwOnTimeout)
|
||||||
throw new TimeoutException(String.Format("Failed to acquire lock '{0}' within the specified timeout ({1}).", internalName, timeout));
|
throw new TimeoutException(String.Format("Failed to acquire lock '{0}' within the specified timeout ({1}).", internalName, timeout));
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dLock;
|
return dLock;
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
Monitor.Exit(monitorObj);
|
Monitor.Exit(monitorObj);
|
||||||
|
|
||||||
Logger.Error(ex, "An error occurred while trying to acquire lock '{0}'.", internalName);
|
Logger.Error(ex, "An error occurred while trying to acquire lock '{0}'.", internalName);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool EnsureDistributedLockRecord(string internalName, TimeSpan? maxValidFor) {
|
private bool EnsureDistributedLockRecord(string internalName, TimeSpan? maxValidFor) {
|
||||||
var localMachineName = _machineNameProvider.GetMachineName();
|
var localMachineName = _machineNameProvider.GetMachineName();
|
||||||
@@ -145,7 +145,7 @@ namespace Orchard.Tasks.Locking.Services {
|
|||||||
if (record == null) {
|
if (record == null) {
|
||||||
// No record existed, so we're good to create a new one.
|
// No record existed, so we're good to create a new one.
|
||||||
Logger.Debug("No valid record was found for lock '{0}'; creating a new record.", internalName);
|
Logger.Debug("No valid record was found for lock '{0}'; creating a new record.", internalName);
|
||||||
|
|
||||||
repository.Create(new DistributedLockRecord {
|
repository.Create(new DistributedLockRecord {
|
||||||
Name = internalName,
|
Name = internalName,
|
||||||
MachineName = localMachineName,
|
MachineName = localMachineName,
|
||||||
@@ -163,7 +163,7 @@ namespace Orchard.Tasks.Locking.Services {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return hasLockRecord;
|
return hasLockRecord;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeleteDistributedLockRecord(string internalName) {
|
private void DeleteDistributedLockRecord(string internalName) {
|
||||||
try {
|
try {
|
||||||
@@ -177,9 +177,9 @@ namespace Orchard.Tasks.Locking.Services {
|
|||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
if (ex.IsFatal())
|
if (ex.IsFatal())
|
||||||
throw;
|
throw;
|
||||||
Logger.Warning(ex, "An error occurred while deleting record for lock '{0}'.", internalName);
|
Logger.Warning(ex, "An error occurred while deleting record for lock '{0}'.", internalName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool RepeatUntilTimeout(TimeSpan? timeout, TimeSpan repeatInterval, Func<bool> action) {
|
private bool RepeatUntilTimeout(TimeSpan? timeout, TimeSpan repeatInterval, Func<bool> action) {
|
||||||
@@ -198,14 +198,14 @@ namespace Orchard.Tasks.Locking.Services {
|
|||||||
if (action == null)
|
if (action == null)
|
||||||
throw new ArgumentNullException();
|
throw new ArgumentNullException();
|
||||||
|
|
||||||
using (var childLifetimeScope = _lifetimeScope.BeginLifetimeScope()) {
|
using (var childLifetimeScope = _lifetimeScope.BeginLifetimeScope()) {
|
||||||
var repository = childLifetimeScope.Resolve<IRepository<DistributedLockRecord>>();
|
var repository = childLifetimeScope.Resolve<IRepository<DistributedLockRecord>>();
|
||||||
var transactionManager = childLifetimeScope.Resolve<ITransactionManager>();
|
var transactionManager = childLifetimeScope.Resolve<ITransactionManager>();
|
||||||
transactionManager.RequireNew(IsolationLevel.ReadCommitted);
|
transactionManager.RequireNew(IsolationLevel.ReadCommitted);
|
||||||
action(repository);
|
action(repository);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private string GetInternalLockName(string name) {
|
private string GetInternalLockName(string name) {
|
||||||
// Prefix the requested lock name by a constant and the tenant name.
|
// Prefix the requested lock name by a constant and the tenant name.
|
||||||
return String.Format("DistributedLock:{0}:{1}", _shellSettings.Name, name);
|
return String.Format("DistributedLock:{0}:{1}", _shellSettings.Name, name);
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Tasks {
|
namespace Orchard.Tasks {
|
||||||
|
|
||||||
@@ -51,6 +52,10 @@ namespace Orchard.Tasks {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
Logger.Warning(ex, "Problem in background tasks");
|
Logger.Warning(ex, "Problem in background tasks");
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.Time {
|
namespace Orchard.Time {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -31,8 +32,11 @@ namespace Orchard.Time {
|
|||||||
TimeZone = TimeZoneInfo.FindSystemTimeZoneById(siteTimeZoneId)
|
TimeZone = TimeZoneInfo.FindSystemTimeZoneById(siteTimeZoneId)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
catch(Exception e) {
|
catch(Exception ex) {
|
||||||
Logger.Error(e, "TimeZone could not be loaded");
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
Logger.Error(ex, "TimeZone could not be loaded");
|
||||||
|
|
||||||
// if the database could not be updated in time, ignore this provider
|
// if the database could not be updated in time, ignore this provider
|
||||||
return null;
|
return null;
|
||||||
|
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
using Orchard.UI.Notify;
|
using Orchard.UI.Notify;
|
||||||
|
using Orchard.Exceptions;
|
||||||
|
|
||||||
namespace Orchard.UI.Admin.Notification {
|
namespace Orchard.UI.Admin.Notification {
|
||||||
public class NotificationManager : INotificationManager {
|
public class NotificationManager : INotificationManager {
|
||||||
@@ -22,8 +23,11 @@ namespace Orchard.UI.Admin.Notification {
|
|||||||
try {
|
try {
|
||||||
return n.GetNotifications();
|
return n.GetNotifications();
|
||||||
}
|
}
|
||||||
catch(Exception e) {
|
catch(Exception ex) {
|
||||||
Logger.Error("An unhandled exception was thrown while generating a notification: " + n.GetType(), e);
|
if (ex.IsFatal()) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
Logger.Error("An unhandled exception was thrown while generating a notification: " + n.GetType(), ex);
|
||||||
return Enumerable.Empty<NotifyEntry>();
|
return Enumerable.Empty<NotifyEntry>();
|
||||||
}
|
}
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
@@ -16,8 +16,7 @@ namespace Orchard.Utility.Extensions {
|
|||||||
var sb = new StringBuilder(camel);
|
var sb = new StringBuilder(camel);
|
||||||
|
|
||||||
for (int i = camel.Length-1; i>0; i--) {
|
for (int i = camel.Length-1; i>0; i--) {
|
||||||
var current = sb[i];
|
if(char.IsUpper(sb[i])) {
|
||||||
if('A' <= current && current <= 'Z') {
|
|
||||||
sb.Insert(i, ' ');
|
sb.Insert(i, ' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,4 +356,4 @@ namespace Orchard.Utility.Extensions {
|
|||||||
return Encoding.UTF8.GetString(Convert.FromBase64String(value));
|
return Encoding.UTF8.GetString(Convert.FromBase64String(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,8 @@
|
|||||||
"gulp-uglify": "^1.2.0",
|
"gulp-uglify": "^1.2.0",
|
||||||
"gulp-rename": "^1.2.2",
|
"gulp-rename": "^1.2.2",
|
||||||
"gulp-concat": "^2.5.2",
|
"gulp-concat": "^2.5.2",
|
||||||
"gulp-header": "^1.2.2"
|
"gulp-header": "^1.2.2",
|
||||||
|
"fs": "^0.0.2"
|
||||||
},
|
},
|
||||||
"dependencies": { }
|
"dependencies": { }
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user