mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Merge branch '1.8.x' into 1.x
Conflicts: src/Orchard.Web/Modules/Orchard.Alias/Implementation/Updater/AliasHolderUpdater.cs src/Orchard.Web/Modules/Orchard.Alias/Orchard.Alias.csproj src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexingTaskExecutor.cs
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.Core.Common.Models;
|
||||
using Orchard.Core.Common.Utilities;
|
||||
using Orchard.Core.Common.ViewModels;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Localization.Services;
|
||||
@@ -51,7 +52,11 @@ namespace Orchard.Core.Common.DateEditor {
|
||||
|
||||
var itemHasNeverBeenPublished = part.PublishedUtc == null;
|
||||
var thisIsTheInitialVersionRecord = part.ContentItem.Version < 2;
|
||||
var theDatesHaveNotBeenModified = part.CreatedUtc == part.VersionCreatedUtc;
|
||||
|
||||
// Dates are assumed the same if the millisecond part is the only difference.
|
||||
// This is because SqlCe doesn't support high precision times (Datetime2) and the infoset does
|
||||
// implying some discrepancies between values read from different storage mechanism.
|
||||
var theDatesHaveNotBeenModified = DateUtils.DatesAreEquivalent(part.CreatedUtc, part.VersionCreatedUtc);
|
||||
|
||||
var theEditorShouldBeBlank =
|
||||
itemHasNeverBeenPublished &&
|
||||
@@ -71,7 +76,6 @@ namespace Orchard.Core.Common.DateEditor {
|
||||
try {
|
||||
var utcDateTime = _dateLocalizationServices.ConvertFromLocalizedString(model.Editor.Date, model.Editor.Time);
|
||||
part.CreatedUtc = utcDateTime;
|
||||
part.VersionCreatedUtc = utcDateTime;
|
||||
}
|
||||
catch (FormatException) {
|
||||
updater.AddModelError(Prefix, T("'{0} {1}' could not be parsed as a valid date and time.", model.Editor.Date, model.Editor.Time));
|
||||
@@ -87,5 +91,6 @@ namespace Orchard.Core.Common.DateEditor {
|
||||
return model;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.Core.Common.Models;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Core.Common.Utilities;
|
||||
|
||||
namespace Orchard.Core.Common.DateEditor {
|
||||
[UsedImplicitly]
|
||||
@@ -13,7 +14,7 @@ namespace Orchard.Core.Common.DateEditor {
|
||||
}
|
||||
|
||||
var thisIsTheInitialVersionRecord = part.ContentItem.Version < 2;
|
||||
var theDatesHaveNotBeenModified = part.CreatedUtc == part.VersionCreatedUtc;
|
||||
var theDatesHaveNotBeenModified = DateUtils.DatesAreEquivalent(part.CreatedUtc, part.VersionCreatedUtc);
|
||||
var theContentDateShouldBeUpdated = thisIsTheInitialVersionRecord && theDatesHaveNotBeenModified;
|
||||
|
||||
if (theContentDateShouldBeUpdated) {
|
||||
|
@@ -49,18 +49,20 @@ namespace Orchard.Core.Common.Handlers {
|
||||
OnPublishing<CommonPart>(AssignPublishingDates);
|
||||
|
||||
OnIndexing<CommonPart>((context, commonPart) => {
|
||||
var utcNow = _clock.UtcNow;
|
||||
|
||||
context.DocumentIndex
|
||||
.Add("type", commonPart.ContentItem.ContentType).Store()
|
||||
.Add("created", commonPart.CreatedUtc ?? _clock.UtcNow).Store()
|
||||
.Add("published", commonPart.PublishedUtc ?? _clock.UtcNow).Store()
|
||||
.Add("modified", commonPart.ModifiedUtc ?? _clock.UtcNow).Store();
|
||||
.Add("created", commonPart.CreatedUtc ?? utcNow).Store()
|
||||
.Add("published", commonPart.PublishedUtc ?? utcNow).Store()
|
||||
.Add("modified", commonPart.ModifiedUtc ?? utcNow).Store();
|
||||
|
||||
if (commonPart.Container != null) {
|
||||
context.DocumentIndex.Add("container-id", commonPart.Container.Id).Store();
|
||||
}
|
||||
|
||||
if (commonPart.Owner != null) {
|
||||
context.DocumentIndex.Add("author", commonPart.Owner.UserName).Analyze().Store();
|
||||
context.DocumentIndex.Add("author", commonPart.Owner.UserName).Store();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -93,6 +95,7 @@ namespace Orchard.Core.Common.Handlers {
|
||||
protected void AssignCreatingDates(InitializingContentContext context, CommonPart part) {
|
||||
// assign default create/modified dates
|
||||
var utcNow = _clock.UtcNow;
|
||||
|
||||
part.CreatedUtc = utcNow;
|
||||
part.ModifiedUtc = utcNow;
|
||||
part.VersionCreatedUtc = utcNow;
|
||||
@@ -101,6 +104,7 @@ namespace Orchard.Core.Common.Handlers {
|
||||
|
||||
private void AssignUpdateDates(UpdateEditorContext context, CommonPart part) {
|
||||
var utcNow = _clock.UtcNow;
|
||||
|
||||
part.ModifiedUtc = utcNow;
|
||||
part.VersionModifiedUtc = utcNow;
|
||||
}
|
||||
@@ -116,16 +120,17 @@ namespace Orchard.Core.Common.Handlers {
|
||||
building.VersionPublishedUtc = null;
|
||||
|
||||
// assign the created
|
||||
building.CreatedUtc = existing.CreatedUtc ?? _clock.UtcNow;
|
||||
building.CreatedUtc = existing.CreatedUtc ?? utcNow;
|
||||
// persist any published dates
|
||||
building.PublishedUtc = existing.PublishedUtc;
|
||||
// assign modified date for the new version
|
||||
building.ModifiedUtc = _clock.UtcNow;
|
||||
building.ModifiedUtc = utcNow;
|
||||
}
|
||||
|
||||
|
||||
protected void AssignPublishingDates(PublishContentContext context, CommonPart part) {
|
||||
var utcNow = _clock.UtcNow;
|
||||
|
||||
part.PublishedUtc = utcNow;
|
||||
part.VersionPublishedUtc = utcNow;
|
||||
}
|
||||
|
44
src/Orchard.Web/Core/Common/Utilities/DateUtils.cs
Normal file
44
src/Orchard.Web/Core/Common/Utilities/DateUtils.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
|
||||
namespace Orchard.Core.Common.Utilities {
|
||||
public class DateUtils {
|
||||
|
||||
/// <summary>
|
||||
/// Compares two <see cref="DateTime" /> instance without their milliseconds portion.
|
||||
/// </summary>
|
||||
/// <param name="a">The first <see cref="DateTime" /> to compare.</param>
|
||||
/// <param name="b">The second <see cref="DateTime" /> to compare.</param>
|
||||
/// <returns><c>True</c> if the two instances are in the same second, <c>False</c> otherwise.</returns>
|
||||
public static bool DatesAreEquivalent(DateTime a, DateTime b) {
|
||||
a = a.ToUniversalTime();
|
||||
b = b.ToUniversalTime();
|
||||
|
||||
return
|
||||
new DateTime(a.Year, a.Month, a.Day, a.Hour, a.Minute, a.Second) ==
|
||||
new DateTime(b.Year, b.Month, b.Day, b.Hour, b.Minute, b.Second);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares two <see cref="DateTime?" /> instance without their milliseconds portion.
|
||||
/// </summary>
|
||||
/// <param name="a">The first <see cref="DateTime?" /> to compare.</param>
|
||||
/// <param name="b">The second <see cref="DateTime?" /> to compare.</param>
|
||||
/// <returns><c>True</c> if the two instances are in the same second, <c>False</c> otherwise.</returns>
|
||||
public static bool DatesAreEquivalent(DateTime? a, DateTime? b) {
|
||||
if (!a.HasValue && !b.HasValue) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (a.HasValue != b.HasValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return DatesAreEquivalent(a.Value, b.Value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -22,8 +22,11 @@ namespace Orchard.Core.Contents.Controllers {
|
||||
public Localizer T { get; set; }
|
||||
|
||||
// /Contents/Item/Display/72
|
||||
public ActionResult Display(int id) {
|
||||
var contentItem = _contentManager.Get(id, VersionOptions.Published);
|
||||
public ActionResult Display(int? id) {
|
||||
if (id == null)
|
||||
return HttpNotFound();
|
||||
|
||||
var contentItem = _contentManager.Get(id.Value, VersionOptions.Published);
|
||||
|
||||
if (contentItem == null)
|
||||
return HttpNotFound();
|
||||
@@ -38,13 +41,16 @@ namespace Orchard.Core.Contents.Controllers {
|
||||
|
||||
// /Contents/Item/Preview/72
|
||||
// /Contents/Item/Preview/72?version=5
|
||||
public ActionResult Preview(int id, int? version) {
|
||||
public ActionResult Preview(int? id, int? version) {
|
||||
if (id == null)
|
||||
return HttpNotFound();
|
||||
|
||||
var versionOptions = VersionOptions.Latest;
|
||||
|
||||
if (version != null)
|
||||
versionOptions = VersionOptions.Number((int)version);
|
||||
|
||||
var contentItem = _contentManager.Get(id, versionOptions);
|
||||
var contentItem = _contentManager.Get(id.Value, versionOptions);
|
||||
if (contentItem == null)
|
||||
return HttpNotFound();
|
||||
|
||||
|
@@ -94,6 +94,7 @@
|
||||
<Compile Include="Common\DateEditor\DateEditorViewModel.cs" />
|
||||
<Compile Include="Common\Settings\TextFieldSettingsEvents.cs" />
|
||||
<Compile Include="Common\Settings\TextFieldSettings.cs" />
|
||||
<Compile Include="Common\Utilities\DateUtils.cs" />
|
||||
<Compile Include="Common\ViewModels\DateTimeEditor.cs" />
|
||||
<Compile Include="Common\ViewModels\TextFieldDriverViewModel.cs" />
|
||||
<Compile Include="Common\ViewModels\TextFieldSettingsEventsViewModel.cs" />
|
||||
|
@@ -42,6 +42,7 @@ namespace Orchard.Core.Scheduling.Services {
|
||||
|
||||
foreach (var taskEntry in taskEntries) {
|
||||
_transactionManager.RequireNew();
|
||||
_contentManager.Clear();
|
||||
|
||||
try {
|
||||
// fetch the task
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Core.Settings.Descriptor.Records;
|
||||
using Orchard.Data;
|
||||
@@ -8,13 +7,14 @@ using Orchard.Environment.Descriptor;
|
||||
using Orchard.Environment.Descriptor.Models;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
using System.Linq;
|
||||
|
||||
namespace Orchard.Core.Settings.Descriptor {
|
||||
public class ShellDescriptorManager : IShellDescriptorManager {
|
||||
public class ShellDescriptorManager : Component, IShellDescriptorManager {
|
||||
private readonly IRepository<ShellDescriptorRecord> _shellDescriptorRepository;
|
||||
private readonly IShellDescriptorManagerEventHandler _events;
|
||||
private readonly ShellSettings _shellSettings;
|
||||
private ShellDescriptorRecord _shellDescriptorRecord;
|
||||
|
||||
public ShellDescriptorManager(
|
||||
IRepository<ShellDescriptorRecord> shellDescriptorRepository,
|
||||
@@ -23,11 +23,8 @@ namespace Orchard.Core.Settings.Descriptor {
|
||||
_shellDescriptorRepository = shellDescriptorRepository;
|
||||
_events = events;
|
||||
_shellSettings = shellSettings;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public ShellDescriptor GetShellDescriptor() {
|
||||
ShellDescriptorRecord shellDescriptorRecord = GetDescriptorRecord();
|
||||
if (shellDescriptorRecord == null) return null;
|
||||
@@ -56,11 +53,7 @@ namespace Orchard.Core.Settings.Descriptor {
|
||||
}
|
||||
|
||||
private ShellDescriptorRecord GetDescriptorRecord() {
|
||||
if (_shellDescriptorRecord == null) {
|
||||
return _shellDescriptorRecord = _shellDescriptorRepository.Table.ToList().SingleOrDefault();
|
||||
}
|
||||
|
||||
return _shellDescriptorRecord;
|
||||
return _shellDescriptorRepository.Get(x => x != null);
|
||||
}
|
||||
|
||||
public void UpdateShellDescriptor(int priorSerialNumber, IEnumerable<ShellFeature> enabledFeatures, IEnumerable<ShellParameter> parameters) {
|
||||
@@ -69,6 +62,8 @@ namespace Orchard.Core.Settings.Descriptor {
|
||||
if (priorSerialNumber != serialNumber)
|
||||
throw new InvalidOperationException(T("Invalid serial number for shell descriptor").ToString());
|
||||
|
||||
Logger.Information("Updating shell descriptor for shell '{0}'...", _shellSettings.Name);
|
||||
|
||||
if (shellDescriptorRecord == null) {
|
||||
shellDescriptorRecord = new ShellDescriptorRecord { SerialNumber = 1 };
|
||||
_shellDescriptorRepository.Create(shellDescriptorRecord);
|
||||
@@ -76,13 +71,12 @@ namespace Orchard.Core.Settings.Descriptor {
|
||||
else {
|
||||
shellDescriptorRecord.SerialNumber++;
|
||||
}
|
||||
|
||||
_shellDescriptorRecord = shellDescriptorRecord;
|
||||
|
||||
shellDescriptorRecord.Features.Clear();
|
||||
foreach (var feature in enabledFeatures) {
|
||||
shellDescriptorRecord.Features.Add(new ShellFeatureRecord { Name = feature.Name, ShellDescriptorRecord = shellDescriptorRecord });
|
||||
}
|
||||
Logger.Debug("Enabled features for shell '{0}' set: {1}.", _shellSettings.Name, String.Join(", ", enabledFeatures.Select(feature => feature.Name)));
|
||||
|
||||
|
||||
shellDescriptorRecord.Parameters.Clear();
|
||||
@@ -94,6 +88,9 @@ namespace Orchard.Core.Settings.Descriptor {
|
||||
ShellDescriptorRecord = shellDescriptorRecord
|
||||
});
|
||||
}
|
||||
Logger.Debug("Parameters for shell '{0}' set: {1}.", _shellSettings.Name, String.Join(", ", parameters.Select(parameter => parameter.Name + "-" + parameter.Value)));
|
||||
|
||||
Logger.Information("Shell descriptor updated for shell '{0}'.", _shellSettings.Name);
|
||||
|
||||
_events.Changed(GetShellDescriptorFromRecord(shellDescriptorRecord), _shellSettings.Name);
|
||||
}
|
||||
|
@@ -137,28 +137,25 @@
|
||||
var _this = $(this);
|
||||
var _controllees = $("[data-controllerid=" + _this.attr("id") + "]");
|
||||
|
||||
var hide = true;
|
||||
|
||||
|
||||
_controllees.each(function () {
|
||||
var _controllee = $(this);
|
||||
var hidden = _controllee.attr("data-defaultstate") == "hidden";
|
||||
var _controlleeIsHidden = _controllee.is(":hidden");
|
||||
|
||||
if (_this.is(":checked") || _this.is(":selected")) {
|
||||
hide = hidden;
|
||||
}
|
||||
else {
|
||||
hide = !hidden;
|
||||
}
|
||||
var hiddenByDefault = _controllee.attr("data-defaultstate") == "hidden";
|
||||
var checkedOrSelected = _this.is(":checked") || _this.is(":selected");
|
||||
|
||||
if (!hide) {
|
||||
if (_controlleeIsHidden) {
|
||||
if (checkedOrSelected) {
|
||||
if (!hiddenByDefault) {
|
||||
_controllee.hide().show(); // <- unhook this when the following comment applies
|
||||
// _controllees.slideUp(200); // <- hook this back up when chrome behaves, or when I care less...or when chrome behaves
|
||||
} else {
|
||||
_controllee.hide();
|
||||
}
|
||||
} else {
|
||||
if (!hiddenByDefault) {
|
||||
_controllee.hide();
|
||||
} else {
|
||||
_controllee.show();
|
||||
}
|
||||
} else if (!_controlleeIsHidden) {
|
||||
// _controllees.slideUp(200); // <- hook this back up when chrome behaves, or when I care less...or when chrome behaves
|
||||
_controllee.hide()
|
||||
}
|
||||
});
|
||||
|
||||
@@ -175,26 +172,16 @@
|
||||
return;
|
||||
}
|
||||
controller.data("isControlling", 1);
|
||||
if (!controller.is(":checked") && !controller.is(":selected")) {
|
||||
$("[data-controllerid=" + controller.attr("id") + "]").hide();
|
||||
}
|
||||
if (controller.is(":checkbox")) {
|
||||
controller.click($(this).toggleWhatYouControl);
|
||||
controller.click($(this).toggleWhatYouControl).each($(this).toggleWhatYouControl);
|
||||
} else if (controller.is(":radio")) {
|
||||
$("[name=" + controller.attr("name") + "]").click(function () { $("[name=" + $(this).attr("name") + "]").each($(this).toggleWhatYouControl); });
|
||||
}
|
||||
else if (controller.is("option")) {
|
||||
controller.parent().change(function () {
|
||||
controller.toggleWhatYouControl();
|
||||
});
|
||||
}).each($(this).toggleWhatYouControl);
|
||||
}
|
||||
|
||||
// if data-defaultstate is 'hidden' hide it by default
|
||||
var hidden = $(this).attr("data-defaultstate") == "hidden";
|
||||
if (hidden) {
|
||||
$(this).hide();
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
// inline form link buttons (form.inline.link button) swapped out for a link that submits said form
|
||||
|
@@ -4,6 +4,7 @@ using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Routing;
|
||||
using Orchard.Alias.Implementation.Holder;
|
||||
using Orchard.Alias.Implementation.Storage;
|
||||
using Orchard.Mvc.Routes;
|
||||
using Orchard.Utility.Extensions;
|
||||
@@ -13,12 +14,15 @@ namespace Orchard.Alias.Implementation {
|
||||
private readonly IAliasStorage _aliasStorage;
|
||||
private readonly IEnumerable<IRouteProvider> _routeProviders;
|
||||
private readonly Lazy<IEnumerable<RouteDescriptor>> _routeDescriptors;
|
||||
private readonly IAliasHolder _aliasHolder;
|
||||
|
||||
public DefaultAliasService(
|
||||
IAliasStorage aliasStorage,
|
||||
IEnumerable<IRouteProvider> routeProviders) {
|
||||
IEnumerable<IRouteProvider> routeProviders,
|
||||
IAliasHolder aliasHolder) {
|
||||
_aliasStorage = aliasStorage;
|
||||
_routeProviders = routeProviders;
|
||||
_aliasHolder = aliasHolder;
|
||||
|
||||
_routeDescriptors = new Lazy<IEnumerable<RouteDescriptor>>(GetRouteDescriptors);
|
||||
}
|
||||
@@ -79,7 +83,37 @@ namespace Orchard.Alias.Implementation {
|
||||
}
|
||||
|
||||
public IEnumerable<string> Lookup(RouteValueDictionary routeValues) {
|
||||
return List().Where(item => item.Item2.Match(routeValues)).Select(item=>item.Item1).ToList();
|
||||
object area;
|
||||
|
||||
if (routeValues.TryGetValue("area", out area)) {
|
||||
// the route has an area, lookup in the specific alias map
|
||||
|
||||
var map = _aliasHolder.GetMap(area.ToString());
|
||||
|
||||
if (map == null) {
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
|
||||
var locate = map.Locate(routeValues);
|
||||
|
||||
if (locate == null) {
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
|
||||
return new[] { locate.Item2 };
|
||||
}
|
||||
|
||||
// no specific area, lookup in all alias maps
|
||||
var result = new List<string>();
|
||||
foreach (var map in _aliasHolder.GetMaps()) {
|
||||
var locate = map.Locate(routeValues);
|
||||
|
||||
if (locate != null) {
|
||||
result.Add(locate.Item2);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public IEnumerable<Tuple<string, RouteValueDictionary>> List() {
|
||||
|
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Orchard.Alias.Implementation.Holder;
|
||||
using Orchard.Alias.Implementation.Storage;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Tasks;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Alias.Implementation.Updater {
|
||||
public class AliasHolderUpdaterTask : IOrchardShellEvents, IBackgroundTask {
|
||||
private readonly IAliasHolderUpdater _aliasHolderUpdater;
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public AliasHolderUpdaterTask(IAliasHolderUpdater aliasHolderUpdater) {
|
||||
_aliasHolderUpdater = aliasHolderUpdater;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
void IOrchardShellEvents.Activated() {
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void IOrchardShellEvents.Terminating() {
|
||||
}
|
||||
|
||||
private void Refresh() {
|
||||
try {
|
||||
_aliasHolderUpdater.Refresh();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.Error(ex, "Exception during Alias refresh");
|
||||
}
|
||||
}
|
||||
|
||||
public void Sweep() {
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
}
|
@@ -76,6 +76,7 @@
|
||||
<Content Include="Views\Admin\Edit.cshtml" />
|
||||
<Content Include="Views\Admin\Index.cshtml" />
|
||||
<Content Include="Web.config" />
|
||||
<Compile Include="Implementation\Updater\AliasHolderUpdater.cs" />
|
||||
<Compile Include="Implementation\Updater\AliasUpdateCursor.cs" />
|
||||
<Compile Include="Implementation\Updater\AliasUpdaterBackgroundTask.cs" />
|
||||
<Compile Include="Implementation\Updater\IAliasUpdateCursor.cs" />
|
||||
@@ -103,7 +104,7 @@
|
||||
<Compile Include="Implementation\Holder\IAliasHolder.cs" />
|
||||
<Compile Include="Implementation\Map\AliasMap.cs" />
|
||||
<Compile Include="Implementation\Storage\AliasStorage.cs" />
|
||||
<Compile Include="Implementation\Updater\AliasHolderUpdater.cs" />
|
||||
<Compile Include="Implementation\Updater\AliasHolderUpdaterTask.cs" />
|
||||
<Compile Include="Implementation\Utils.cs" />
|
||||
<Compile Include="Migrations.cs" />
|
||||
<Compile Include="Records\ActionRecord.cs" />
|
||||
|
@@ -80,6 +80,13 @@ namespace Orchard.Autoroute.Handlers {
|
||||
part.DisplayAlias = _autorouteService.Value.GenerateAlias(part);
|
||||
}
|
||||
|
||||
// if the generated alias is empty, compute a new one
|
||||
if (String.IsNullOrWhiteSpace(part.DisplayAlias)) {
|
||||
_autorouteService.Value.ProcessPath(part);
|
||||
_orchardServices.Notifier.Warning(T("The permalink could not be generated, a new slug has been defined: \"{0}\"", part.Path));
|
||||
return;
|
||||
}
|
||||
|
||||
// should it become the home page ?
|
||||
if (part.DisplayAlias != "/" && _orchardServices.Authorizer.Authorize(Permissions.SetHomePage)) {
|
||||
// if it's the current home page, do nothing
|
||||
|
@@ -89,6 +89,7 @@ namespace Orchard.Azure.MediaServices.Services.Assets {
|
||||
pendingAsset.UploadState.BytesComplete = 0;
|
||||
pendingAsset.UploadState.CompletedUtc = null;
|
||||
_transactionManager.RequireNew();
|
||||
_contentManager.Clear();
|
||||
|
||||
var assetProgressMoniker = Guid.NewGuid();
|
||||
var assetCancellationTokenSource = new CancellationTokenSource();
|
||||
@@ -185,6 +186,7 @@ namespace Orchard.Azure.MediaServices.Services.Assets {
|
||||
if ((_clock.UtcNow - lastUpdateUtc).Seconds >= 5) {
|
||||
progressAsset.UploadState.BytesComplete = progressInfo.Data.BytesTransferred;
|
||||
_transactionManager.RequireNew();
|
||||
_contentManager.Clear();
|
||||
lastUpdateUtc = _clock.UtcNow;
|
||||
}
|
||||
|
||||
|
@@ -31,7 +31,7 @@ namespace Orchard.Comments.Models {
|
||||
set { Record.UserName = value; }
|
||||
}
|
||||
|
||||
[RegularExpression(@"^(?![\.@])(""([^""\r\\]|\\[""\r\\])*""|([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$")]
|
||||
[RegularExpression(@"^(?![\.@])(""([^""\r\\]|\\[""\r\\])*""|([-\w!#$%&'*+/=?^`{|}~]|(?<!\.)\.)*)(?<!\.)@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$")]
|
||||
public string Email {
|
||||
get { return Record.Email; }
|
||||
set { Record.Email = value; }
|
||||
|
@@ -139,7 +139,13 @@ namespace Orchard.DesignerTools.Services {
|
||||
}
|
||||
|
||||
foreach (var member in members) {
|
||||
if (o is ContentItem && member.Name == "ContentManager"
|
||||
if ((o is ContentItem && (member.Name == "ContentManager"
|
||||
|| member.Name == "Parts"
|
||||
|| member.Name == "Record"
|
||||
|| member.Name == "VersionRecord"
|
||||
|| member.Name == "TypeDefinition"
|
||||
|| member.Name == "TypePartDefinition"
|
||||
|| member.Name == "PartDefinition"))
|
||||
|| o is Delegate
|
||||
|| o is Type
|
||||
) {
|
||||
|
@@ -33,6 +33,7 @@ namespace Orchard.Indexing.Services {
|
||||
private readonly ShellSettings _shellSettings;
|
||||
private readonly ILockFileManager _lockFileManager;
|
||||
private readonly IClock _clock;
|
||||
private readonly ITransactionManager _transactionManager;
|
||||
private const int ContentItemsPerLoop = 50;
|
||||
private IndexingStatus _indexingStatus = IndexingStatus.Idle;
|
||||
|
||||
@@ -44,7 +45,8 @@ namespace Orchard.Indexing.Services {
|
||||
IAppDataFolder appDataFolder,
|
||||
ShellSettings shellSettings,
|
||||
ILockFileManager lockFileManager,
|
||||
IClock clock) {
|
||||
IClock clock,
|
||||
ITransactionManager transactionManager) {
|
||||
_taskRepository = taskRepository;
|
||||
_contentRepository = contentRepository;
|
||||
_indexManager = indexManager;
|
||||
@@ -52,6 +54,7 @@ namespace Orchard.Indexing.Services {
|
||||
_appDataFolder = appDataFolder;
|
||||
_shellSettings = shellSettings;
|
||||
_lockFileManager = lockFileManager;
|
||||
_transactionManager = transactionManager;
|
||||
_clock = clock;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
@@ -143,34 +146,38 @@ namespace Orchard.Indexing.Services {
|
||||
private bool BatchIndex(string indexName, string settingsFilename, IndexSettings indexSettings) {
|
||||
var addToIndex = new List<IDocumentIndex>();
|
||||
var deleteFromIndex = new List<int>();
|
||||
bool loop = false;
|
||||
|
||||
// Rebuilding the index ?
|
||||
if (indexSettings.Mode == IndexingMode.Rebuild) {
|
||||
Logger.Information("Rebuilding index");
|
||||
_indexingStatus = IndexingStatus.Rebuilding;
|
||||
|
||||
// load all content items
|
||||
var contentItems = _contentRepository
|
||||
do {
|
||||
loop = true;
|
||||
|
||||
// load all content items
|
||||
var contentItems = _contentRepository
|
||||
.Table.Where(versionRecord => versionRecord.Latest && versionRecord.Id > indexSettings.LastContentId)
|
||||
.OrderBy(versionRecord => versionRecord.Id)
|
||||
.Take(ContentItemsPerLoop)
|
||||
.ToList()
|
||||
.Select(versionRecord => _contentManager.Get(versionRecord.ContentItemRecord.Id, VersionOptions.VersionRecord(versionRecord.Id)))
|
||||
.Distinct()
|
||||
.ToList();
|
||||
.OrderBy(versionRecord => versionRecord.Id)
|
||||
.Take(ContentItemsPerLoop)
|
||||
.ToList()
|
||||
.Select(versionRecord => _contentManager.Get(versionRecord.ContentItemRecord.Id, VersionOptions.VersionRecord(versionRecord.Id)))
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
// if no more elements to index, switch to update mode
|
||||
if (contentItems.Count == 0) {
|
||||
indexSettings.Mode = IndexingMode.Update;
|
||||
}
|
||||
// if no more elements to index, switch to update mode
|
||||
if (contentItems.Count == 0) {
|
||||
indexSettings.Mode = IndexingMode.Update;
|
||||
}
|
||||
|
||||
foreach (var item in contentItems) {
|
||||
try {
|
||||
foreach (var item in contentItems) {
|
||||
try {
|
||||
|
||||
var settings = GetTypeIndexingSettings(item);
|
||||
var settings = GetTypeIndexingSettings(item);
|
||||
|
||||
// skip items from types which are not indexed
|
||||
if (settings.List.Contains(indexName)) {
|
||||
if (settings.List.Contains(indexName)) {
|
||||
if (item.HasPublished()) {
|
||||
var published = _contentManager.Get(item.Id, VersionOptions.Published);
|
||||
IDocumentIndex documentIndex = ExtractDocumentIndex(published);
|
||||
@@ -181,66 +188,88 @@ namespace Orchard.Indexing.Services {
|
||||
}
|
||||
}
|
||||
else if (settings.List.Contains(indexName + ":latest")) {
|
||||
IDocumentIndex documentIndex = ExtractDocumentIndex(item);
|
||||
IDocumentIndex documentIndex = ExtractDocumentIndex(item);
|
||||
|
||||
if (documentIndex != null && documentIndex.IsDirty) {
|
||||
addToIndex.Add(documentIndex);
|
||||
if (documentIndex != null && documentIndex.IsDirty) {
|
||||
addToIndex.Add(documentIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
indexSettings.LastContentId = item.VersionRecord.Id;
|
||||
indexSettings.LastContentId = item.VersionRecord.Id;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.Warning(ex, "Unable to index content item #{0} during rebuild", item.Id);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.Warning(ex, "Unable to index content item #{0} during rebuild", item.Id);
|
||||
|
||||
if (contentItems.Count < ContentItemsPerLoop) {
|
||||
loop = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_transactionManager.RequireNew();
|
||||
_contentManager.Clear();
|
||||
}
|
||||
|
||||
|
||||
} while (loop);
|
||||
}
|
||||
|
||||
if (indexSettings.Mode == IndexingMode.Update) {
|
||||
Logger.Information("Updating index");
|
||||
_indexingStatus = IndexingStatus.Updating;
|
||||
|
||||
var indexingTasks = _taskRepository
|
||||
.Table.Where(x => x.Id > indexSettings.LastIndexedId)
|
||||
.OrderBy(x => x.Id)
|
||||
.Take(ContentItemsPerLoop)
|
||||
.ToList()
|
||||
.GroupBy(x => x.ContentItemRecord.Id)
|
||||
do {
|
||||
var indexingTasks = _taskRepository
|
||||
.Table.Where(x => x.Id > indexSettings.LastIndexedId)
|
||||
.OrderBy(x => x.Id)
|
||||
.Take(ContentItemsPerLoop)
|
||||
.ToList()
|
||||
.GroupBy(x => x.ContentItemRecord.Id)
|
||||
.Select(group => new { TaskId = group.Max(task => task.Id), Delete = group.Last().Action == IndexingTaskRecord.Delete, Id = group.Key, ContentItem = _contentManager.Get(group.Key, VersionOptions.Latest) })
|
||||
.OrderBy(x => x.TaskId)
|
||||
.ToArray();
|
||||
.OrderBy(x => x.TaskId)
|
||||
.ToArray();
|
||||
|
||||
foreach (var item in indexingTasks) {
|
||||
try {
|
||||
foreach (var item in indexingTasks) {
|
||||
try {
|
||||
|
||||
IDocumentIndex documentIndex = null;
|
||||
IDocumentIndex documentIndex = null;
|
||||
|
||||
// item.ContentItem can be null if the content item has been deleted
|
||||
if (item.ContentItem != null) {
|
||||
// skip items from types which are not indexed
|
||||
var settings = GetTypeIndexingSettings(item.ContentItem);
|
||||
if (settings.List.Contains(indexName)) {
|
||||
documentIndex = ExtractDocumentIndex(item.ContentItem);
|
||||
}
|
||||
// item.ContentItem can be null if the content item has been deleted
|
||||
if (item.ContentItem != null) {
|
||||
// skip items from types which are not indexed
|
||||
var settings = GetTypeIndexingSettings(item.ContentItem);
|
||||
if (settings.List.Contains(indexName)) {
|
||||
documentIndex = ExtractDocumentIndex(item.ContentItem);
|
||||
}
|
||||
else if (settings.List.Contains(indexName + ":latest")) {
|
||||
var latest = _contentManager.Get(item.Id, VersionOptions.Latest);
|
||||
documentIndex = ExtractDocumentIndex(latest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (documentIndex == null || item.Delete) {
|
||||
deleteFromIndex.Add(item.Id);
|
||||
}
|
||||
else if (documentIndex.IsDirty) {
|
||||
addToIndex.Add(documentIndex);
|
||||
}
|
||||
if (documentIndex == null || item.Delete) {
|
||||
deleteFromIndex.Add(item.Id);
|
||||
}
|
||||
else if (documentIndex.IsDirty) {
|
||||
addToIndex.Add(documentIndex);
|
||||
}
|
||||
|
||||
indexSettings.LastIndexedId = item.TaskId;
|
||||
indexSettings.LastIndexedId = item.TaskId;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.Warning(ex, "Unable to index content item #{0} during update", item.Id);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.Warning(ex, "Unable to index content item #{0} during update", item.Id);
|
||||
|
||||
if (indexingTasks.Length < ContentItemsPerLoop) {
|
||||
loop = false;
|
||||
}
|
||||
else {
|
||||
_transactionManager.RequireNew();
|
||||
_contentManager.Clear();
|
||||
}
|
||||
}
|
||||
while (loop);
|
||||
}
|
||||
|
||||
// save current state of the index
|
||||
|
@@ -8,6 +8,6 @@ namespace Orchard.Localization.ViewModels {
|
||||
[Required]
|
||||
public string SelectedCulture { get; set; }
|
||||
public IEnumerable<string> SiteCultures { get; set; }
|
||||
public IContent Content { get; set; }
|
||||
public dynamic Content { get; set; }
|
||||
}
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
@model Orchard.Localization.ViewModels.AddLocalizationViewModel
|
||||
@using Orchard.ContentManagement;
|
||||
@{
|
||||
Style.Require("LocalizationAdmin");
|
||||
}
|
||||
@@ -11,6 +12,6 @@
|
||||
<div>
|
||||
@T("This is the <em>{0}</em> variation of {1}",
|
||||
Html.DropDownList("SelectedCulture", new SelectList(siteCultures, Model.SelectedCulture)),
|
||||
Html.ItemEditLink(Model.Content))
|
||||
Html.ItemEditLink((ContentItem)Model.Content.ContentItem))
|
||||
</div>
|
||||
</fieldset>
|
@@ -137,7 +137,7 @@ namespace Orchard.MediaProcessing.Services {
|
||||
descriptor.Filter(filterContext);
|
||||
}
|
||||
|
||||
_fileNameProvider.UpdateFileName(profileName, path, filterContext.FilePath);
|
||||
_fileNameProvider.UpdateFileName(profileName, System.Web.HttpUtility.UrlDecode(path), filterContext.FilePath);
|
||||
|
||||
if (!filterContext.Saved) {
|
||||
try {
|
||||
|
@@ -1,4 +1,6 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Orchard.Commands;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.MultiTenancy.Services;
|
||||
@@ -42,6 +44,16 @@ namespace Orchard.MultiTenancy.Commands {
|
||||
[OrchardSwitches("Host,UrlPrefix")]
|
||||
public void Create(string tenantName) {
|
||||
Context.Output.WriteLine(T("Creating tenant"));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(tenantName) || !Regex.IsMatch(tenantName, @"^\w+$")) {
|
||||
Context.Output.WriteLine(T("Invalid tenant name. Must contain characters only and no spaces."));
|
||||
return;
|
||||
}
|
||||
if (_tenantService.GetTenants().Any(tenant => string.Equals(tenant.Name, tenantName, StringComparison.OrdinalIgnoreCase))) {
|
||||
Context.Output.WriteLine(T("Could not create tenant \"{0}\". A tenant with the same name already exists.", tenantName));
|
||||
return;
|
||||
}
|
||||
|
||||
_tenantService.CreateTenant(
|
||||
new ShellSettings {
|
||||
Name = tenantName,
|
||||
|
@@ -9,7 +9,6 @@ using Orchard.MultiTenancy.Services;
|
||||
using Orchard.MultiTenancy.ViewModels;
|
||||
using Orchard.Security;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.Utility.Extensions;
|
||||
|
||||
namespace Orchard.MultiTenancy.Controllers {
|
||||
[ValidateInput(false)]
|
||||
@@ -52,11 +51,17 @@ namespace Orchard.MultiTenancy.Controllers {
|
||||
|
||||
[HttpPost, ActionName("Add")]
|
||||
public ActionResult AddPOST(TenantAddViewModel viewModel) {
|
||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Couldn't create tenant")))
|
||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Couldn't create tenant"))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
if (!EnsureDefaultTenant())
|
||||
if (!EnsureDefaultTenant()) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
if (_tenantService.GetTenants().Any(tenant => string.Equals(tenant.Name, viewModel.Name, StringComparison.OrdinalIgnoreCase))) {
|
||||
ModelState.AddModelError("Name", T("A tenant with the same name already exists.", viewModel.Name).Text);
|
||||
}
|
||||
|
||||
// ensure tenants name are valid
|
||||
if (!String.IsNullOrEmpty(viewModel.Name) && !Regex.IsMatch(viewModel.Name, @"^\w+$")) {
|
||||
|
@@ -27,6 +27,8 @@
|
||||
|
||||
<fieldset class="publish-later-datetime">
|
||||
<legend>@T("Publish")</legend>
|
||||
@Html.HiddenFor(m => m.Editor.ShowDate)
|
||||
@Html.HiddenFor(m => m.Editor.ShowTime)
|
||||
@Html.EditorFor(m => m.Editor)
|
||||
<button type="submit" name="submit.Save" value="submit.PublishLater">@T("Publish Later")</button>
|
||||
</fieldset>
|
||||
|
@@ -67,8 +67,9 @@ namespace Orchard.Recipes.RecipeHandlers {
|
||||
};
|
||||
|
||||
foreach (var arg in args) {
|
||||
// Switch?
|
||||
if (arg[0] == '/') {
|
||||
if (arg.StartsWith("/")) {
|
||||
//If arg is not empty and starts with '/'
|
||||
|
||||
int index = arg.IndexOf(':');
|
||||
var switchName = (index < 0 ? arg.Substring(1) : arg.Substring(1, index - 1));
|
||||
var switchValue = (index < 0 || index >= arg.Length ? string.Empty : arg.Substring(index + 1));
|
||||
|
@@ -62,8 +62,8 @@ namespace Orchard.Recipes.RecipeHandlers {
|
||||
|
||||
//Create a new transaction for each batch
|
||||
if (startIndex < elementDictionary.Count) {
|
||||
_orchardServices.ContentManager.Clear();
|
||||
_transactionManager.RequireNew();
|
||||
_orchardServices.ContentManager.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,30 +1,34 @@
|
||||
<?xml version="1.0"?>
|
||||
<Orchard>
|
||||
<Recipe>
|
||||
<Name>Search</Name>
|
||||
<Description>Configures a default search index and search settings using the Lucene engine.</Description>
|
||||
<Author>The Orchard Team</Author>
|
||||
<WebSite>http://orchardproject.net</WebSite>
|
||||
<Tags>developer</Tags>
|
||||
<Version>1.0</Version>
|
||||
</Recipe>
|
||||
<Recipe>
|
||||
<Name>Search</Name>
|
||||
<Description>Configures a default search index and search settings using the Lucene engine.</Description>
|
||||
<Author>The Orchard Team</Author>
|
||||
<WebSite>http://orchardproject.net</WebSite>
|
||||
<Tags>developer</Tags>
|
||||
<Version>1.0</Version>
|
||||
</Recipe>
|
||||
|
||||
<Feature enable="Orchard.Search,Lucene" />
|
||||
|
||||
<Metadata>
|
||||
<Types>
|
||||
<Page TypeIndexing.Indexes="Search">
|
||||
</Page>
|
||||
<BlogPost TypeIndexing.Indexes="Search">
|
||||
</BlogPost>
|
||||
</Types>
|
||||
</Metadata>
|
||||
<Feature enable="Orchard.Search,Lucene" />
|
||||
|
||||
<Migration features="*" />
|
||||
|
||||
<Command>
|
||||
index create Search
|
||||
index update Search
|
||||
search use Search
|
||||
</Command>
|
||||
<Metadata>
|
||||
<Types>
|
||||
<Page TypeIndexing.Indexes="Search">
|
||||
</Page>
|
||||
<BlogPost TypeIndexing.Indexes="Search">
|
||||
</BlogPost>
|
||||
</Types>
|
||||
</Metadata>
|
||||
|
||||
<Migration features="*" />
|
||||
|
||||
<Command>
|
||||
index create Search
|
||||
index update Search
|
||||
</Command>
|
||||
|
||||
<Settings>
|
||||
<SearchSettingsPart SearchedFields="body,title" FilterCulture="false" SearchIndex="Search" />
|
||||
</Settings>
|
||||
|
||||
</Orchard>
|
||||
|
@@ -49,6 +49,10 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="NHibernate, Version=3.3.1.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\lib\nhibernate\NHibernate.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
|
@@ -19,17 +19,20 @@ namespace Orchard.Tags.Services {
|
||||
private readonly INotifier _notifier;
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly IOrchardServices _orchardServices;
|
||||
private readonly ISessionFactoryHolder _sessionFactoryHolder;
|
||||
|
||||
public TagService(IRepository<TagRecord> tagRepository,
|
||||
IRepository<ContentTagRecord> contentTagRepository,
|
||||
INotifier notifier,
|
||||
IAuthorizationService authorizationService,
|
||||
IOrchardServices orchardServices) {
|
||||
IOrchardServices orchardServices,
|
||||
ISessionFactoryHolder sessionFactoryHolder) {
|
||||
_tagRepository = tagRepository;
|
||||
_contentTagRepository = contentTagRepository;
|
||||
_notifier = notifier;
|
||||
_authorizationService = authorizationService;
|
||||
_orchardServices = orchardServices;
|
||||
_sessionFactoryHolder = sessionFactoryHolder;
|
||||
Logger = NullLogger.Instance;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
@@ -207,6 +210,11 @@ namespace Orchard.Tags.Services {
|
||||
}
|
||||
|
||||
contentItem.As<TagsPart>().CurrentTags = tagNamesForContentItem;
|
||||
|
||||
var sessionFactory = _sessionFactoryHolder.GetSessionFactory();
|
||||
|
||||
if (sessionFactory != null)
|
||||
sessionFactory.EvictCollection("Orchard.Tags.Models.TagsPartRecord.Tags", contentItem.As<TagsPart>().Record.Id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -8,6 +8,7 @@ using Orchard.Taxonomies.Models;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Data;
|
||||
using Orchard.Taxonomies.Settings;
|
||||
using System;
|
||||
|
||||
namespace Orchard.Taxonomies.Handlers {
|
||||
[UsedImplicitly]
|
||||
@@ -23,7 +24,7 @@ namespace Orchard.Taxonomies.Handlers {
|
||||
OnPublished<TaxonomyPart>((context, part) => {
|
||||
var previousTermTypeName = part.TermTypeName;
|
||||
|
||||
if (previousName == null || part.Name == previousName) {
|
||||
if (previousName == null) {
|
||||
// is it a new taxonomy ?
|
||||
taxonomyService.CreateTermContentType(part);
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@ Features:
|
||||
Name: Templates
|
||||
Description: Provides a Template type that represents a shape template, stored as a content item.
|
||||
Category: Content
|
||||
Dependencies: Contents, Orchard.Tokens
|
||||
Dependencies: Contents, Orchard.Tokens, Orchard.Core
|
||||
Orchard.Templates.Razor:
|
||||
Name: Razor Templates
|
||||
Description: Extends Templates with Razor templates.
|
||||
|
@@ -176,7 +176,7 @@
|
||||
<Compile Include="Services\TemplateProcessorImpl.cs" />
|
||||
<Compile Include="Services\RazorTemplateProcessor.cs" />
|
||||
<Compile Include="Services\DefaultTemplateService.cs" />
|
||||
<Compile Include="Services\TemplateShapeDisplayEvent.cs" />
|
||||
<Compile Include="Services\TemplateShapeBindingResolver.cs" />
|
||||
<Compile Include="Settings\ShapePartSettings.cs" />
|
||||
<Compile Include="Settings\ShapePartSettingsEvents.cs" />
|
||||
<Compile Include="ViewModels\ShapePartSettingsViewModel.cs" />
|
||||
|
@@ -0,0 +1,83 @@
|
||||
using Orchard.Caching;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.DisplayManagement.Implementation;
|
||||
using Orchard.Templates.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.DisplayManagement.Descriptors;
|
||||
|
||||
namespace Orchard.Templates.Services {
|
||||
public class TemplateShapeBindingResolver : IShapeBindingResolver {
|
||||
private ICacheManager _cacheManager;
|
||||
private ISignals _signals;
|
||||
private IContentManager _contentManager;
|
||||
private ITemplateService _templateService;
|
||||
|
||||
public TemplateShapeBindingResolver(
|
||||
ICacheManager cacheManager,
|
||||
ISignals signals,
|
||||
IContentManager contentManager,
|
||||
ITemplateService templateService
|
||||
) {
|
||||
_cacheManager = cacheManager;
|
||||
_signals = signals;
|
||||
_contentManager = contentManager;
|
||||
_templateService = templateService;
|
||||
}
|
||||
|
||||
public bool TryGetDescriptorBinding(string shapeType, out ShapeBinding shapeBinding) {
|
||||
var processors = BuildShapeProcessors();
|
||||
|
||||
TemplateResult templateResult = null;
|
||||
if (processors.TryGetValue(shapeType, out templateResult)) {
|
||||
shapeBinding = new ShapeBinding {
|
||||
BindingName = "Templates",
|
||||
Binding = ctx => CoerceHtmlString(_templateService.Execute(
|
||||
templateResult.Template,
|
||||
templateResult.Name,
|
||||
templateResult.Processor, ctx.Value))
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
shapeBinding = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private IDictionary<string, TemplateResult> BuildShapeProcessors() {
|
||||
return _cacheManager.Get("Template.ShapeProcessors", ctx => {
|
||||
ctx.Monitor(_signals.When(DefaultTemplateService.TemplatesSignal));
|
||||
|
||||
var allTemplates = _contentManager.Query<ShapePart>().List();
|
||||
|
||||
return allTemplates.Select(x => {
|
||||
var name = x.Name;
|
||||
var template = x.Template;
|
||||
var processorName = x.ProcessorName;
|
||||
|
||||
return new TemplateResult {
|
||||
Name = x.Name,
|
||||
Template = x.Template,
|
||||
Processor = x.ProcessorName
|
||||
};
|
||||
|
||||
}).ToDictionary(x => x.Name, x => x);
|
||||
});
|
||||
}
|
||||
|
||||
private static IHtmlString CoerceHtmlString(object invoke) {
|
||||
return invoke as IHtmlString ?? (invoke != null ? new HtmlString(invoke.ToString()) : null);
|
||||
}
|
||||
|
||||
private class TemplateResult {
|
||||
public string Name { get; set; }
|
||||
public string Processor { get; set; }
|
||||
public string Template { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,59 +0,0 @@
|
||||
using Orchard.Caching;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.DisplayManagement.Implementation;
|
||||
using Orchard.Templates.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace Orchard.Templates.Services {
|
||||
public class TemplateShapeDisplayEvent : IShapeDisplayEvents {
|
||||
private ICacheManager _cacheManager;
|
||||
private ISignals _signals;
|
||||
private IContentManager _contentManager;
|
||||
private ITemplateService _templateService;
|
||||
|
||||
public TemplateShapeDisplayEvent(
|
||||
ICacheManager cacheManager,
|
||||
ISignals signals,
|
||||
IContentManager contentManager,
|
||||
ITemplateService templateService
|
||||
) {
|
||||
_cacheManager = cacheManager;
|
||||
_signals = signals;
|
||||
_contentManager = contentManager;
|
||||
_templateService = templateService;
|
||||
}
|
||||
|
||||
public void Displaying(ShapeDisplayingContext context) {
|
||||
var processors = BuildShapeProcessors();
|
||||
Func<dynamic, IHtmlString> processor;
|
||||
|
||||
if (processors.TryGetValue(context.ShapeMetadata.Type, out processor)) {
|
||||
context.ChildContent = processor(context.Shape);
|
||||
}
|
||||
}
|
||||
|
||||
public void Displayed(ShapeDisplayedContext context) {
|
||||
}
|
||||
|
||||
public IDictionary<string, Func<dynamic, IHtmlString>> BuildShapeProcessors() {
|
||||
return _cacheManager.Get("Template.ShapeProcessors", ctx => {
|
||||
ctx.Monitor(_signals.When(DefaultTemplateService.TemplatesSignal));
|
||||
|
||||
var allTemplates = _contentManager.Query<ShapePart>().List();
|
||||
|
||||
return allTemplates.Select(x => new KeyValuePair<string, Func<dynamic, IHtmlString>>(
|
||||
x.Name,
|
||||
d => CoerceHtmlString(_templateService.Execute(x.Template, x.Name, x.ProcessorName, d))
|
||||
)).ToDictionary(x => x.Key, x => x.Value);
|
||||
});
|
||||
}
|
||||
|
||||
private static IHtmlString CoerceHtmlString(object invoke) {
|
||||
return invoke as IHtmlString ?? (invoke != null ? new HtmlString(invoke.ToString()) : null);
|
||||
}
|
||||
}
|
||||
}
|
27
src/Orchard/Data/Conventions/UtcDateTimeConvention.cs
Normal file
27
src/Orchard/Data/Conventions/UtcDateTimeConvention.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using FluentNHibernate.Conventions;
|
||||
using FluentNHibernate.Conventions.AcceptanceCriteria;
|
||||
using FluentNHibernate.Conventions.Inspections;
|
||||
using FluentNHibernate.Conventions.Instances;
|
||||
using NHibernate.Type;
|
||||
|
||||
namespace Orchard.Data.Conventions {
|
||||
public class UtcDateTimeConvention : IPropertyConvention, IPropertyConventionAcceptance {
|
||||
public void Apply(IPropertyInstance instance) {
|
||||
instance.CustomType<UtcDateTimeType>();
|
||||
}
|
||||
|
||||
public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria) {
|
||||
criteria.Expect(x =>
|
||||
x.Property.Name.EndsWith("Utc", StringComparison.OrdinalIgnoreCase) && (
|
||||
x.Property.PropertyType.Equals(typeof(DateTime)) ||
|
||||
x.Property.PropertyType.Equals(typeof(DateTime?))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@@ -90,6 +90,8 @@ namespace Orchard.Data.Migration {
|
||||
|
||||
// apply update methods to each migration class for the module
|
||||
foreach (var migration in migrations) {
|
||||
_transactionManager.RequireNew();
|
||||
|
||||
// copy the object for the Linq query
|
||||
var tempMigration = migration;
|
||||
|
||||
@@ -102,8 +104,6 @@ namespace Orchard.Data.Migration {
|
||||
}
|
||||
|
||||
try {
|
||||
_transactionManager.RequireNew();
|
||||
|
||||
// do we need to call Create() ?
|
||||
if (current == 0) {
|
||||
// try to resolve a Create method
|
||||
|
@@ -91,6 +91,7 @@ namespace Orchard.Data.Providers {
|
||||
.Conventions.Setup(x => x.Add(AutoImport.Never()))
|
||||
.Conventions.Add(new RecordTableNameConvention(recordDescriptors))
|
||||
.Conventions.Add(new CacheConventions(recordDescriptors))
|
||||
.Conventions.Add(new UtcDateTimeConvention())
|
||||
.Alterations(alt => {
|
||||
foreach (var recordAssembly in recordDescriptors.Select(x => x.Type.Assembly).Distinct()) {
|
||||
alt.Add(new AutoMappingOverrideAlteration(recordAssembly));
|
||||
|
@@ -142,6 +142,10 @@ namespace Orchard.Data {
|
||||
var pathName = GetPathName(_shellSettings.Name);
|
||||
hash.AddString(_appDataFolder.MapPath(pathName).ToLowerInvariant());
|
||||
|
||||
// Orchard version, to rebuild the mappings for each new version
|
||||
var orchardVersion = new System.Reflection.AssemblyName(typeof(Orchard.ContentManagement.ContentItem).Assembly.FullName).Version.ToString();
|
||||
hash.AddString(orchardVersion);
|
||||
|
||||
// Shell settings data
|
||||
hash.AddString(_shellSettings.DataProvider);
|
||||
hash.AddString(_shellSettings.DataTablePrefix);
|
||||
|
@@ -15,8 +15,6 @@ namespace Orchard.Data {
|
||||
private readonly ISessionFactoryHolder _sessionFactoryHolder;
|
||||
private readonly IEnumerable<ISessionInterceptor> _interceptors;
|
||||
private ISession _session;
|
||||
private ITransaction _transaction;
|
||||
private bool _cancelled;
|
||||
|
||||
public SessionLocator(
|
||||
ISessionFactoryHolder sessionFactoryHolder,
|
||||
@@ -32,19 +30,13 @@ namespace Orchard.Data {
|
||||
|
||||
public ISession For(Type entityType) {
|
||||
Logger.Debug("Acquiring session for {0}", entityType);
|
||||
|
||||
((ITransactionManager)this).Demand();
|
||||
Demand();
|
||||
|
||||
return _session;
|
||||
}
|
||||
|
||||
public void Demand() {
|
||||
EnsureSession();
|
||||
|
||||
if (_transaction == null) {
|
||||
Logger.Debug("Creating transaction on Demand");
|
||||
_transaction = _session.BeginTransaction(IsolationLevel);
|
||||
}
|
||||
EnsureSession(IsolationLevel);
|
||||
}
|
||||
|
||||
public void RequireNew() {
|
||||
@@ -52,71 +44,48 @@ namespace Orchard.Data {
|
||||
}
|
||||
|
||||
public void RequireNew(IsolationLevel level) {
|
||||
EnsureSession();
|
||||
|
||||
if (_cancelled) {
|
||||
if (_transaction != null) {
|
||||
_transaction.Rollback();
|
||||
_transaction.Dispose();
|
||||
_transaction = null;
|
||||
}
|
||||
|
||||
_cancelled = false;
|
||||
}
|
||||
else {
|
||||
if (_transaction != null) {
|
||||
_transaction.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Debug("Creating new transaction with isolation level {0}", level);
|
||||
_transaction = _session.BeginTransaction(level);
|
||||
DisposeSession();
|
||||
EnsureSession(level);
|
||||
}
|
||||
|
||||
public void Cancel() {
|
||||
Logger.Debug("Transaction cancelled flag set");
|
||||
_cancelled = true;
|
||||
if (_session!= null && !_session.Transaction.WasRolledBack && _session.Transaction.IsActive) {
|
||||
Logger.Debug("Rolling back transaction");
|
||||
_session.Transaction.Rollback();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
if (_transaction != null) {
|
||||
try {
|
||||
if (!_cancelled) {
|
||||
Logger.Debug("Marking transaction as complete");
|
||||
_transaction.Commit();
|
||||
}
|
||||
else {
|
||||
Logger.Debug("Reverting operations from transaction");
|
||||
_transaction.Rollback();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
Logger.Error(e, "Error while disposing the transaction.");
|
||||
}
|
||||
finally {
|
||||
_transaction.Dispose();
|
||||
Logger.Debug("Transaction disposed");
|
||||
|
||||
_transaction = null;
|
||||
_cancelled = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_session != null) {
|
||||
_session.Dispose();
|
||||
_session = null;
|
||||
}
|
||||
|
||||
DisposeSession();
|
||||
}
|
||||
|
||||
private void EnsureSession() {
|
||||
private void DisposeSession() {
|
||||
if (_session != null) {
|
||||
|
||||
try {
|
||||
if (!_session.Transaction.WasRolledBack && _session.Transaction.IsActive) {
|
||||
Logger.Debug("Committing transaction");
|
||||
_session.Transaction.Commit();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
Logger.Debug("Disposing session");
|
||||
_session.Close();
|
||||
_session.Dispose();
|
||||
_session = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureSession(IsolationLevel level) {
|
||||
if (_session != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var sessionFactory = _sessionFactoryHolder.GetSessionFactory();
|
||||
Logger.Information("Opening database session");
|
||||
Logger.Debug("Opening NHibernate session");
|
||||
_session = sessionFactory.OpenSession(new OrchardSessionInterceptor(_interceptors.ToArray(), Logger));
|
||||
_session.BeginTransaction(level);
|
||||
}
|
||||
|
||||
class OrchardSessionInterceptor : IInterceptor {
|
||||
|
9
src/Orchard/DisplayManagement/IShapeBindingResolver.cs
Normal file
9
src/Orchard/DisplayManagement/IShapeBindingResolver.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.DisplayManagement.Descriptors;
|
||||
using Orchard.DisplayManagement.Shapes;
|
||||
|
||||
namespace Orchard.DisplayManagement {
|
||||
public interface IShapeBindingResolver : IDependency {
|
||||
bool TryGetDescriptorBinding(string shapeType, out ShapeBinding shapeBinding);
|
||||
}
|
||||
}
|
@@ -18,6 +18,7 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
private readonly IWorkContextAccessor _workContextAccessor;
|
||||
private readonly IEnumerable<IShapeDisplayEvents> _shapeDisplayEvents;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly IEnumerable<IShapeBindingResolver> _shapeBindingResolvers;
|
||||
|
||||
// this need to be Shape instead of IShape - cast to interface throws error on clr types like HtmlString
|
||||
private static readonly CallSite<Func<CallSite, object, Shape>> _convertAsShapeCallsite = CallSite<Func<CallSite, object, Shape>>.Create(
|
||||
@@ -30,12 +31,15 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
public DefaultDisplayManager(
|
||||
IWorkContextAccessor workContextAccessor,
|
||||
IEnumerable<IShapeDisplayEvents> shapeDisplayEvents,
|
||||
IEnumerable<IShapeBindingResolver> shapeBindingResolvers,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
Lazy<IShapeTableLocator> shapeTableLocator) {
|
||||
_shapeTableLocator = shapeTableLocator;
|
||||
_workContextAccessor = workContextAccessor;
|
||||
_shapeDisplayEvents = shapeDisplayEvents;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_shapeBindingResolvers = shapeBindingResolvers;
|
||||
|
||||
T = NullLocalizer.Instance;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
@@ -135,12 +139,19 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
return shape.Metadata.ChildContent;
|
||||
}
|
||||
|
||||
static bool TryGetDescriptorBinding(string shapeType, IEnumerable<string> shapeAlternates, ShapeTable shapeTable, out ShapeBinding shapeBinding) {
|
||||
private bool TryGetDescriptorBinding(string shapeType, IEnumerable<string> shapeAlternates, ShapeTable shapeTable, out ShapeBinding shapeBinding) {
|
||||
// shape alternates are optional, fully qualified binding names
|
||||
// the earliest added alternates have the lowest priority
|
||||
// the descriptor returned is based on the binding that is matched, so it may be an entirely
|
||||
// different descriptor if the alternate has a different base name
|
||||
foreach (var shapeAlternate in shapeAlternates.Reverse()) {
|
||||
|
||||
foreach (var shapeBindingResolver in _shapeBindingResolvers) {
|
||||
if(shapeBindingResolver.TryGetDescriptorBinding(shapeAlternate, out shapeBinding)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shapeTable.Bindings.TryGetValue(shapeAlternate, out shapeBinding)) {
|
||||
return true;
|
||||
}
|
||||
@@ -151,6 +162,12 @@ namespace Orchard.DisplayManagement.Implementation {
|
||||
// so the shapetype itself may contain a longer alternate forms that falls back to a shorter one
|
||||
var shapeTypeScan = shapeType;
|
||||
for (; ; ) {
|
||||
foreach (var shapeBindingResolver in _shapeBindingResolvers) {
|
||||
if (shapeBindingResolver.TryGetDescriptorBinding(shapeTypeScan, out shapeBinding)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shapeTable.Bindings.TryGetValue(shapeTypeScan, out shapeBinding)) {
|
||||
return true;
|
||||
}
|
||||
|
@@ -19,13 +19,13 @@ namespace Orchard.Environment.Configuration {
|
||||
}
|
||||
|
||||
IEnumerable<ShellSettings> IShellSettingsManager.LoadSettings() {
|
||||
Logger.Debug("Reading ShellSettings...");
|
||||
Logger.Information("Reading ShellSettings...");
|
||||
var settingsList = LoadSettingsInternal().ToArray();
|
||||
|
||||
var tenantNamesQuery =
|
||||
from settings in settingsList
|
||||
select settings.Name;
|
||||
Logger.Debug("Returning {0} ShellSettings objects for tenants {1}.", tenantNamesQuery.Count(), String.Join(", ", tenantNamesQuery));
|
||||
Logger.Information("Returning {0} ShellSettings objects for tenants {1}.", tenantNamesQuery.Count(), String.Join(", ", tenantNamesQuery));
|
||||
|
||||
return settingsList;
|
||||
}
|
||||
@@ -36,11 +36,11 @@ namespace Orchard.Environment.Configuration {
|
||||
if (String.IsNullOrEmpty(settings.Name))
|
||||
throw new ArgumentException("The Name property of the supplied ShellSettings object is null or empty; the settings cannot be saved.", "settings");
|
||||
|
||||
Logger.Debug("Saving ShellSettings for tenant '{0}'...", settings.Name);
|
||||
Logger.Information("Saving ShellSettings for tenant '{0}'...", settings.Name);
|
||||
var filePath = Path.Combine(Path.Combine("Sites", settings.Name), _settingsFileName);
|
||||
_appDataFolder.CreateFile(filePath, ShellSettingsSerializer.ComposeSettings(settings));
|
||||
|
||||
Logger.Debug("ShellSettings saved successfully; flagging tenant '{0}' for restart.", settings.Name);
|
||||
Logger.Information("ShellSettings saved successfully; flagging tenant '{0}' for restart.", settings.Name);
|
||||
_events.Saved(settings);
|
||||
}
|
||||
|
||||
|
@@ -15,11 +15,9 @@ namespace Orchard.FileSystems.Dependencies {
|
||||
/// </summary>
|
||||
public class DynamicModuleVirtualPathProvider : VirtualPathProvider, ICustomVirtualPathProvider {
|
||||
private readonly IExtensionDependenciesManager _extensionDependenciesManager;
|
||||
private readonly IEnumerable<IExtensionLoader> _loaders;
|
||||
|
||||
public DynamicModuleVirtualPathProvider(IExtensionDependenciesManager extensionDependenciesManager, IEnumerable<IExtensionLoader> loaders) {
|
||||
public DynamicModuleVirtualPathProvider(IExtensionDependenciesManager extensionDependenciesManager) {
|
||||
_extensionDependenciesManager = extensionDependenciesManager;
|
||||
_loaders = loaders;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
|
34
src/Orchard/FileSystems/Media/StorageProviderExtensions.cs
Normal file
34
src/Orchard/FileSystems/Media/StorageProviderExtensions.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Orchard.FileSystems.Media {
|
||||
public static class StorageProviderExtensions {
|
||||
public static void WriteAllText(this IStorageProvider storageProvider, string path, string contents) {
|
||||
if (storageProvider.FileExists(path)) {
|
||||
storageProvider.DeleteFile(path);
|
||||
}
|
||||
|
||||
var file = storageProvider.CreateFile(path);
|
||||
using (var stream = file.OpenWrite())
|
||||
using (var streamWriter = new StreamWriter(stream)) {
|
||||
streamWriter.Write(contents);
|
||||
}
|
||||
}
|
||||
|
||||
public static string ReadAllText(this IStorageProvider storageProvider, string path) {
|
||||
if (!storageProvider.FileExists(path)) {
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
var file = storageProvider.GetFile(path);
|
||||
using (var stream = file.OpenRead())
|
||||
using (var streamReader = new StreamReader(stream)) {
|
||||
return streamReader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -171,6 +171,7 @@
|
||||
<Compile Include="ContentManagement\Utilities\ComputedField.cs" />
|
||||
<Compile Include="Data\AbstractSessionInterceptor.cs" />
|
||||
<Compile Include="Data\Bags\SArray.cs" />
|
||||
<Compile Include="Data\Conventions\UtcDateTimeConvention.cs" />
|
||||
<Compile Include="Data\FetchRequest.cs" />
|
||||
<Compile Include="Data\Migration\Interpreters\MySqlCommandInterpreter.cs" />
|
||||
<Compile Include="Data\Providers\MySqlStatementProvider.cs" />
|
||||
@@ -207,6 +208,7 @@
|
||||
<Compile Include="DisplayManagement\Implementation\IShapeDisplayEvents.cs" />
|
||||
<Compile Include="DisplayManagement\Implementation\IShapeFactoryEvents.cs" />
|
||||
<Compile Include="DisplayManagement\INamedEnumerable.cs" />
|
||||
<Compile Include="DisplayManagement\IShapeBindingResolver.cs" />
|
||||
<Compile Include="DisplayManagement\IShapeDisplay.cs" />
|
||||
<Compile Include="DisplayManagement\ShapeDisplay.cs" />
|
||||
<Compile Include="DisplayManagement\Shapes\Composite.cs" />
|
||||
@@ -256,6 +258,7 @@
|
||||
<Compile Include="FileSystems\Media\ConfigurationMimeTypeProvider.cs" />
|
||||
<Compile Include="FileSystems\Media\FileSystemStorageProvider.cs" />
|
||||
<Compile Include="FileSystems\Media\IMimeTypeProvider.cs" />
|
||||
<Compile Include="FileSystems\Media\StorageProviderExtensions.cs" />
|
||||
<Compile Include="Indexing\ISearchBits.cs" />
|
||||
<Compile Include="Localization\HtmlLocalizationExtensions.cs" />
|
||||
<Compile Include="Localization\Models\DateLocalizationOptions.cs" />
|
||||
|
@@ -2,7 +2,9 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.Data;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Logging;
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.Tasks {
|
||||
|
||||
@@ -14,10 +16,18 @@ namespace Orchard.Tasks {
|
||||
public class BackgroundService : IBackgroundService {
|
||||
private readonly IEnumerable<IBackgroundTask> _tasks;
|
||||
private readonly ITransactionManager _transactionManager;
|
||||
private readonly string _shellName;
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
public BackgroundService(IEnumerable<IBackgroundTask> tasks, ITransactionManager transactionManager) {
|
||||
public BackgroundService(
|
||||
IEnumerable<IBackgroundTask> tasks,
|
||||
ITransactionManager transactionManager,
|
||||
ShellSettings shellSettings,
|
||||
IContentManager contentManager) {
|
||||
_tasks = tasks;
|
||||
_transactionManager = transactionManager;
|
||||
_shellName = shellSettings.Name;
|
||||
_contentManager = contentManager;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
@@ -26,14 +36,14 @@ namespace Orchard.Tasks {
|
||||
public void Sweep() {
|
||||
foreach(var task in _tasks) {
|
||||
try {
|
||||
_contentManager.Clear();
|
||||
_transactionManager.RequireNew();
|
||||
task.Sweep();
|
||||
}
|
||||
catch (Exception e) {
|
||||
_transactionManager.Cancel();
|
||||
Logger.Error(e, "Error while processing background task");
|
||||
Logger.Error(e, "Error while processing background task on tenant '{0}'.", _shellName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user